スクリプトはゼロで終了し、トンネルが現れ、次回の実行はパスワードを尋ねる前に拒否される。あるいは同じコマンドが端末では動くのに、スケジュールされたジョブからは「イベントが見つかりません」という役に立たないエラーで失敗する。どちらもネットワーク障害ではなく、AnyConnect クライアントの標準入力での対話が崩れているのだ。ログインを台本化された問答として扱えば、失敗は予測可能で小さくなる。

同じコマンドがスクリプト内で失敗する理由

クライアントは標準入力から回答を、プロンプトごとに一行ずつ、ゲートウェイが尋ねる順序どおりに読む。プロンプトの数が変わるもの、たとえば新しいバナー、グループ選択、二要素目の要求があると、以降の回答はすべて一行ずつずれる。するとクライアントはパスワードを期待した位置でユーザー名を読み、どちらも指さない失敗を報告する。

感嘆符を含むパスワードは、より静かな二つ目の失敗を加える。二重引用符の中では、クライアントが何かを見るよりずっと前にシェルが展開してしまう。

ペイロードを一重引用符で囲めば、文字はそのまま運ばれる。それが修正のすべてであり、同じ資格情報が入力時には通り、保存時には失敗するという報告の一団を説明する。ゲートウェイを調べる前に、正確なバイトを示すラッパー経由でペイロードを出力して行数を数え、シェルが何をしたかを調べよ。こうした調査のほとんどはそこで終わる。

クライアントが尋ねる順序で回答を書く

クライアントを一度対話的に実行し、すべてのプロンプトを順に書き留める。グループ選択はゲートウェイが複数のプロファイルを公開しているときだけ現れ、バナーのプロンプトは設定されているときだけ現れる。回答ファイルは、実際に向いているゲートウェイに合わせる必要があり、ドキュメントのものではない。

次に、その正確な順序で、一行に一つの回答という形でファイルを組み立てる。グループの索引はクライアントが一覧に出す番号であり、文書内のプロファイルの位置ではない。バナーはゲートウェイが送る場合にだけ受け入れ、そのゲートウェイが尋ねると分かっている追加の質問ごとに行を足す。クライアントは非対話フラグ付きで起動し、端末を待たずにファイルを消費させる。

connect vpn.lab.example
0
username
password
y
exit
/opt/cisco/anyconnect/bin/vpn -s < anyconnect.txt

ディスクにファイルを置きたくない場合は、同じ順序をパイプから流すこともできる。引用の規則が、それが生き残るかを決める。

資格情報をプロセス一覧の外に置く

コマンドライン引数はプロセスの存続中ずっとローカルの全ユーザーから読めるので、パスワードはファイルかパイプに属し、引数一覧には決して置かない。そのファイルはスクリプトを実行するアカウントだけが読めるようにし、ジョブが終わったら削除する。macOS でもバイナリは通常 Linux と同じ場所にあるが、決めつけずにインストール先を確認する。両方のパスを試すラッパーは、障害報告書より短い。

printf 'username\npassword\ny\n' | /opt/cisco/anyconnect/bin/vpn -s connect vpn.lab.example

スクリプトに無限の再試行をさせてもいけない。バナーが変わったり、夜のうちにパスワードが失効したりすると、固定の回答ファイルは再試行ループに変わり、そのループがアカウントをロックする。

一度失敗したら、クライアント自身のエラーテキストを出力して終了する。スケジュールされたジョブには、静かに失効する資格情報が午前三時の障害と区別できないため、他の無人タスクと同じく身元と資格情報の可用性の見直しが必要だ。

終了コードを信じる前にセッションを確認する

接続済みの状態はトンネルが存在することを示すだけで、それ以上ではない。スクリプトが実際の作業を始める前に、そこを通じて到達できるはずのリソースを一つ試し、そこの失敗はログイン失敗とは別の障害として扱う。そうしなければ、宛先に届かないだけの完全に良好な接続を再試行することになる。

切断の前と後にクライアントへ状態を尋ねるのは、古いセッションが次の接続を拒否する一方でスクリプトが成功を報告していることがあるからだ。

/opt/cisco/anyconnect/bin/vpn state
/opt/cisco/anyconnect/bin/vpn disconnect

状態の出力を終了コードの隣に記録するのは、コードだけでは拒否されたログインと決して閉じなかったセッションを区別できないからだ。ゲートウェイが二要素目や対話的な承認を求める場合は、その手順をスクリプト化するのをやめ、代わりにクライアントが対応する仕組みを使う。固定の回答ファイルは自分が管理する資格情報のための便宜であり、管理していない認証手順を回避する手段ではない。範囲をそこまで狭く保てば、短いスクリプトのままでいられる。

固定の回答ファイルが適さない場合

二要素目や承認のプロンプトはこのパターンを完全に打ち破り、それはスクリプトの難題ではなく設計上の境界だ。 その手順についてクライアントが対応する仕組みを使う 事前に回答を推測するのではなく。固定ファイルは実行ごとに変わらない資格情報にしか使えない。

古い二つの資格情報の形式も AnyConnect と混同される。vpnc プロファイルは別のプロトコルを話し、グループ名を IPSec 識別子として求め、次に共有グループ秘密、その次に自分のアカウント情報を求める。

プロトコルが異なるため、vpnc は AnyConnect プロファイルだけを公開するゲートウェイには到達できず、そのサービスで通常使われるオープンな代替は、anyconnect プロトコルを選んだ openconnect だ。pcf ファイルは旧来の Cisco クライアントのもので、そのホスト、グループ名、グループパスワードをまだ Cisco IPsec を話すクライアントに再入力できても、ファイルはクライアント間で引き継がれない。特殊なポートや非標準のトンネリング方式は、その移行で通常失われる。どのプロトコルをゲートウェイが提供するかを決めてから道具を選ぶこと。

関連記事