OpenVPN の auth-user-pass-verify スクリプト:終了コードを正しく決める
フックの終了ステータスこそが判断であり、ログの行ではない。検証結果を 0、1、保留にマッピングし、資格情報ファイルをデータとして読み、失敗時は閉じる。
OpenVPN はログインスクリプトの出力をちょうど一つだけ見ます。終了ステータスです。スクリプトが行う他のことはすべて飾りです。フックは正しい検証器に到達し、応答を解析し、親しみやすい行を出力しながら、作者の意図とは逆の意味のステータスを返すことがあります。契約を先に読み、その周りにアダプターを書けば、その種のバグは丸ごと消えます。
契約は小さいものです。送信されたアカウントを特定し、承認された検証器に意図した問いを投げ、その要求についてその検証器の文書化された肯定的な結果だけを受け入れます。残りはすべて配管です。
フックが返せる三つのステータス
auth-user-pass-verify については、OpenVPN 2.6 のマニュアルが終了コード 0 を受理、1 を拒否、2 を保留認証と定義しています。サーバーが理解する答えはこの三つだけで、それぞれ接続への影響が異なります。最後のコマンドのステータスで終了するスクリプトは、実質的にログ呼び出しや後片付けの手順に票を投じさせています。到達しなかった分岐も含め、すべての分岐でステータスを明示的に書いてください。
HTTP の成功と認証の成功は別の層であり、これを混同することがこのフックが誤る最も一般的な原因です。202 応答は要求が処理のために受け付けられたという意味で、パスワードが検証されたという意味ではありません。期待するステータス、応答の形、最終的な判定は与えられた API 契約から定義し、もっともらしいからといってフィールド名をでっち上げないでください。
答えが本当に後から届くなら、それが保留の経路であり、そう作る必要があります。決して完了しない保留の試行は、タイムアウトが切れるまでリソースを保持します。
資格情報ファイルは書かれたとおりに読む
文書化されたファイル経由の方式では、サーバーはユーザー名とパスワードを一時ファイルの最初の二行として書き、そのパスをスクリプトに渡し、スクリプトが戻るとファイルを削除します。この二行はデータとして読んでください。ファイルを source してはいけません。評価してもいけません。プロセステーブルから見えるコマンドラインに内容を貼り付けてはいけません。パスワードはバイト単位で保持してください。ユーザー名を正規化するのと同じように正規化すると、資格情報が静かに変わります。その一時ファイルのディレクトリは配備上の判断なので、存在することと、ホスト上の全員が読める状態でないことを確認してください。
検証器自身の資格情報はユーザーのものと分けてください。ゲートウェイ連携に属し、プラットフォームのシークレットストアに置かれ、検証の権限だけを必要とするので、特定の人物が認証された証拠にはなりません。フックを 二つ目のパスワード検証器にしてはいけません。ハッシュ比較を手で書き直しても、ループを最適化しても安全にはならず、保守された検証器はアカウントストアのソルト付きでコストのかかる方式をすでに理解しています。
分類できない答えの意味を決める
タイムアウト、転送エラー、壊れた応答、利用できないバックエンドには共通点が一つあります。どれも肯定的な検証ではないということです。フックはそのそれぞれに対して閉じたまま失敗し、運用者が対応できる理由を記録すべきです。その理由は保護されたログに置くもので、接続しようとしている人に返すメッセージではありません。
検証器にまったく届かない経路にも同じだけ注意してください。設定値の欠落、読めないシークレット、未インストールの依存関係は、偶発的な受理ではなく、明確な運用マーカー付きの拒否を生むべきです。そうした分岐は、頭で考えるのではなく、ラボで依存関係を外して試してください。ログの失敗が終了ステータスを変えうる場所では、ログは判断の一部になっており、無害にしなければなりません。
サーバー設定もここでは重要です。ユーザー定義スクリプトは、実行中の設定が必要なセキュリティレベルで許可している場合にのみ尊重され、その設定は引き上げるべき既定値ではなく、意図的な選択です。
判定を検証する。印字された行ではない
終了ステータスを直接調べるテストを組み立ててください。サンプルの資格情報ファイルを書き、既知の正常なアカウントと既知の不良なアカウントでフックを実行し、スクリプトが印字するテキストではなくシェルが報告するステータスを読みます。この一つの確認で、クライアントが接続する前に契約のバグのほとんどを捕まえられます。
次に同じケースを実クライアントから非本番のリスナーに対して実行し、サーバーが何を記録したかを確認します。受理、拒否、保留のいずれかです。無効化されたアカウント、誤ったパスワード、壊れた検証器の応答、タイムアウト、到達不能な検証器を網羅してください。どれかのケースが名前を付けられない状態に落ちるなら、アダプターは未完成です。
検証結果から終了ステータスへの対応表をリポジトリでスクリプトの隣に置き、次のエンジニアがコードをリバースエンジニアリングせずに契約を読めるようにしてください。