Keenetic: пробрасывать pre-auth куку из 401 GET /auth в POST /auth (X-Detail: no session)
build-and-deploy / build (push) Successful in 2m20s
build-and-deploy / deploy (push) Successful in 1m5s

This commit is contained in:
Kayashov.SM
2026-08-28 22:34:43 +04:00
parent c6fa6f3870
commit fb34e9b03a
3 changed files with 37 additions and 8 deletions
+26 -4
View File
@@ -43,10 +43,28 @@ jobs:
- name: Сборка и публикация образа
run: |
# docker build/push ходят наружу (Docker Hub, при первой сборке слоя — ещё и Maven
# Central) по тому же нестабильному пути, что раньше ронял пул образа раннера — там
# были TCP-таймауты/обрывы, которые лечатся повтором, а не переделкой шага. Поэтому
# оборачиваем оба во retry с паузой: 5 попыток, между ними 15с.
retry() {
local attempt=1
local max=5
until "$@"; do
if [ "$attempt" -ge "$max" ]; then
echo "::error::'$*' не удалось за $max попыток(ки), сдаюсь"
return 1
fi
echo "'$*' — попытка $attempt из $max не удалась, жду 15с и повторяю..."
attempt=$((attempt + 1))
sleep 15
done
}
IMAGE="docker.io/$DOCKERHUB_USER/iot-hub"
docker build -t "$IMAGE:${GITHUB_SHA}" -t "$IMAGE:latest" .
docker push "$IMAGE:${GITHUB_SHA}"
docker push "$IMAGE:latest"
retry docker build -t "$IMAGE:${GITHUB_SHA}" -t "$IMAGE:latest" .
retry docker push "$IMAGE:${GITHUB_SHA}"
retry docker push "$IMAGE:latest"
env:
DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
@@ -71,7 +89,11 @@ jobs:
- name: Установка Helm
run: |
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
# raw.githubusercontent.com — тот же ненадёжный путь. --retry у curl умеет повторять
# сам, без ручного цикла: 5 попыток, экспоненциальная задержка, повтор и на сетевых
# обрывах (--retry-all-errors), не только на HTTP-кодах.
curl -fsSL --retry 5 --retry-delay 5 --retry-all-errors \
-o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod +x get_helm.sh
./get_helm.sh
rm get_helm.sh
@@ -133,15 +133,22 @@ public class KeeneticRouterClient {
"Keenetic RCI: роутер не прислал X-NDM-Challenge/X-NDM-Realm в ответ на GET /auth — "
+ "формат авторизации мог снова измениться");
}
// Диагностика (X-Detail: "0x2021, no session") показала: 401 на GET /auth сам по себе
// ставит pre-auth сессионную куку, к которой привязан именно этот challenge. Раньше мы
// её игнорировали и слали POST /auth вообще без Cookie — роутер не мог сопоставить
// решённый challenge ни с какой сессией и отвечал 400. Сохраняем куку из 401 и шлём
// её на POST — так же, как обычный запрос уже шлёт actualную сессионную куку.
storeCookie(challengeHeaders);
String hash = sha256Hex(challenge + md5Hex(properties.getLogin() + ":" + realm + ":" + properties.getPassword()));
Map<String, String> body = Map.of("login", properties.getLogin(), "password", hash);
// Хэш — SHA-256, необратимый, логировать его безопасно (в отличие от самого пароля).
// INFO, а не DEBUG — это временная диагностика (400 Bad Request на POST /auth не даёт
// тела ответа, причина пока не установлена), чтобы не пришлось менять уровень логов.
log.info("Keenetic RCI: POST {} login={} challenge={} realm={} hash={}",
authUrl, properties.getLogin(), challenge, realm, hash);
log.info("Keenetic RCI: POST {} login={} challenge={} realm={} hash={} cookie={}",
authUrl, properties.getLogin(), challenge, realm, hash, sessionCookie);
try {
ResponseEntity<Void> authResponse = restTemplate.postForEntity(authUrl, body, Void.class);
HttpEntity<Object> entity = new HttpEntity<>(body, authHeaders());
ResponseEntity<Void> authResponse = restTemplate.postForEntity(authUrl, entity, Void.class);
storeCookie(authResponse.getHeaders());
} catch (HttpStatusCodeException authError) {
log.error("Keenetic RCI: POST /auth -> {} ({}); заголовки ответа: {}; тело ответа: '{}'",
+1 -1
View File
@@ -42,7 +42,7 @@ resources:
# в то, что здесь — см. README.md, раздел "Конфигурация без Helm-редеплоя".
adapters:
camera:
enabled: true
enabled: false
urls: []
# - "https://example.com/stream1/master.m3u8"
keenetic: