Salt 3008.3 salt-call emits an unconsumed AsyncAuth SystemExit traceback while its minion key is pending

オープン
#70,705 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 3 日以内に返信

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
42/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
python

調査の方向性

Start with AsyncAuth._authenticate() in salt/crypt.py around line 1275 and compare its pending-key handling with the retry result from SAuth.sign_in(). Trace how the authentication future is consumed and where salt-call handles authentication failures. Done means a pending key produces a clean failure suitable for retry, while rejection, fingerprint or signature errors, and transport failures remain distinguishable.

索引モデルが issue の本文から書いたものです。

説明

What happened?

Reproduction with a master: configure a minion for a reachable master without accepting its public key. Run salt-call --retcode-passthrough --out=json pillar.items unmask=True. Keep the key pending and repeat. Once the key is accepted, the call succeeds.

Expected: pending authentication produces a short diagnostic and a clean failure status suitable for a bounded enrollment retry loop.

Actual: the pending branch in AsyncAuth._authenticate() at salt/crypt.py:1275 calls sys.exit(2). The resulting unconsumed task exception produces a traceback ending in SystemExit: 2. Repeating the ordinary CLI invocation repeats the traceback even though enrollment can later succeed.

Suggested direction: propagate a typed pending-authentication exception/result through the authentication future and translate it to the CLI exit code at the caller boundary, preserving distinct rejection, fingerprint/signature, and transport failures. The synchronous SAuth.sign_in() already returns a retry result without taking this crashing branch. Related historical report: https://github.com/saltstack/salt/issues/22811 (closed as stale).

Minimal no-master reproduction of the task defect:

import asyncio
import gc
import pathlib
import tempfile
from unittest.mock import AsyncMock, MagicMock, patch
import salt.config
import salt.crypt

with tempfile.TemporaryDirectory() as directory:
    root = pathlib.Path(directory)
    (root / "pki").mkdir()
    opts = salt.config.minion_config(str(root / "minion"))
    opts.update(master_uri="tcp://127.0.0.1:4506", caller=True,
                pki_dir=str(root / "pki"), cachedir=str(root / "cache"))
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    channel = MagicMock()
    channel.__aenter__ = AsyncMock(return_value=channel)
    channel.__aexit__ = AsyncMock(return_value=False)
    with patch("salt.channel.client.AsyncReqChannel.factory", return_value=channel), \
            patch.object(salt.crypt.AsyncAuth, "sign_in", new=AsyncMock(return_value="retry")):
        auth = salt.crypt.AsyncAuth(opts, io_loop=loop)
        auth.authenticate()
        try:
            loop.run_forever()
        except SystemExit as error:
            print(f"Caught caller exit {error.code}; authentication future done={auth._authenticate_future.done()}")
        finally:
            loop.close()
    channel.reset_mock()
    gc.collect()
Type of salt install

Onedir

Major version

3008.x

What supported OS are you seeing the problem on? Can select multiple. (If bug appears on an unsupported OS, please open a GitHub Discussion instead)

ubuntu-24.04

salt --versions-report output
Salt: 3008.3 (Linux onedir, bundled Python 3.14)

Full salt-call --versions-report from an affected minion to follow in a comment. The task behavior also reproduces with pip Salt 3008.3 / Tornado 6.6 on Python 3.14.9 and 3.11.17.

主要言語
Python
スター
15.8k
フォーク
5.6k
平均マージ
5日 9時間
マージ済み PR(30日)
99

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

saltstack/salt のほかの issue

saltstack/salt の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。