fix(telegram): BUTTON_DATA_INVALID — nonce 超過 64 bytes 根因修復
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
根因:Telegram callback_data 上限 64 bytes。 5 個長 action 名(docker_restart/host_restart_service 等)+ UUID approval_id = 71-77 bytes → BUTTON_DATA_INVALID。 修復: 1. security_interceptor.generate_callback_nonce:若 nonce > 63 bytes, 改用 3-part 格式(捨棄 random)— timestamp 仍保時間唯一性。 2. security_interceptor.parse_callback_data:接受 3-part 或 4-part 格式。 3. telegram_gateway:移除 debug payload logging(診斷完成)。 影響 action:docker_restart / host_restart_service / host_clear_log / reload_nginx / renew_cert(全部 > 7 chars + UUID = 64 bytes 以上)。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -411,10 +411,17 @@ class TelegramSecurityInterceptor:
|
||||
|
||||
nonce = f"{action}:{approval_id}:{timestamp}:{random_part}"
|
||||
|
||||
# Telegram callback_data limit is 64 bytes.
|
||||
# Long action names (e.g. docker_restart=14 chars) with UUID approval_id push nonce to 71+ bytes.
|
||||
# Drop the random suffix when over limit — timestamp still guarantees temporal uniqueness.
|
||||
if len(nonce.encode()) > 63:
|
||||
nonce = f"{action}:{approval_id}:{timestamp}"
|
||||
|
||||
logger.debug(
|
||||
"callback_nonce_generated",
|
||||
approval_id=approval_id,
|
||||
action=action,
|
||||
nonce_len=len(nonce.encode()),
|
||||
)
|
||||
|
||||
return nonce
|
||||
@@ -447,7 +454,8 @@ class TelegramSecurityInterceptor:
|
||||
"is_info_action": True,
|
||||
}
|
||||
|
||||
if len(parts) != 4:
|
||||
# 接受 3-part(長 action 名截斷 random)和 4-part(標準)兩種格式
|
||||
if len(parts) not in (3, 4):
|
||||
raise ValueError(f"Invalid callback_data format: {callback_data}")
|
||||
|
||||
return {
|
||||
|
||||
@@ -1378,14 +1378,6 @@ class TelegramGateway:
|
||||
) as span:
|
||||
try:
|
||||
response = await self._http_client.post(url, json=payload)
|
||||
if response.status_code >= 400:
|
||||
import json as _json
|
||||
_payload_str = _json.dumps(payload, ensure_ascii=False)
|
||||
logger.error("telegram_api_rejected", method=method,
|
||||
status=response.status_code,
|
||||
response_body=response.text[:300],
|
||||
payload_len=len(_payload_str),
|
||||
payload_preview=_payload_str[:1000])
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user