2つのtailnetの罠:古いキーが別のネットワークを編集していた
お客様は、リースしたMacにTailscale経由で接続します。SSHのアクセスルールはtailnetのポリシーに置き、そのルールをコードで管理しています。リースが始まるとお客様のアドレスが追加され、終わると削除されます。小さくて退屈なシステムです。ところがある日、すべてのお客様がアクセスを失ったと報告してきました。それは嘘でした。
ツールが報告したこと
定期チェックが、お客様用のSSHルールが空だと告げました。有料のお客様3人が接続できなくなった、というのです。マシンへのアクセスを売っている事業にとっては、最大級の警報です。
ルールは空ではありませんでした。当社が別のtailnetを読んでいたのです。
2つのネットワーク、1つの別名
アカウントには2つのtailnetがありました。1つはフリート用です。リースしたMac、ハブ、お客様への共有がすべてここにあります。もう1つは、セットアップ時に残った古い個人用のネットワークで、止まったマシン1台とノートPCがあるだけでした。
Tailscale APIでは、tailnetを名前で指定するか、「呼び出したキーが属するtailnet」という意味の-を渡します。当社のコードは-を渡していました。キーが1つなら問題ありません。キーは見分けのつかない文字列なので、-は環境にあるほうのキーに黙って従います。ある設定ファイルに、古いキーが紛れ込んでいました。
危険だったのは書き込み
嘘をつく読み取りは、午後を無駄にします。嘘をつく書き込みは、インシデントを起こします。同じツールには、アクセスルールを現在のお客様に合わせて修正するモードがあります。それを間違ったtailnetに対して実行したところ、実在するお客様3人のメールアドレスを、古いネットワークのポリシーに律儀に書き込みました。そこでは何の効果もありませんでした。
実際に影響を受けたお客様はいません。フリートのtailnetには一度も手が触れられず、ずっと正しい状態だったからです。それでも数分間、自動処理は間違ったネットワークのアクセス制御を編集し、成功と報告していました。
修正:ネットワークを名前で指定する
-を渡すのをやめました。現在のコードは、フリートのtailnetを明示的に指定しています。それが見えないキーは、見えるものに流されるのではなく、はっきり失敗します。
現在は、実行のたびに通信したtailnetを表示します。その行がフリートでなければ、その下の結果には意味がありません。それに基づいて行動する前に、そのことがわかります。
一般的な教訓
「この認証情報が指す先ならどこでも」という意味の便利なデフォルトは、認証情報が2つ以上になった瞬間に罠になります。間違ったキーが、エラーではなく黙った転送先の変更になってしまうからです。書き込みをするものは、対象を名前で指定すべきです。そうすれば、間違った認証情報を使ったときに、意図しない場所で成功するのではなく、失敗します。
これは失敗しようがない確認処理で書いたほかの静かな失敗と同じ形です。ツールは自信満々でした。ツールは間違っていました。そして、編集しているネットワークの名前を表示するまで、出力からはそれがわかりませんでした。
よくある質問
- TailscaleのAPIキーは、どのtailnetを編集するかをどう決めるのですか?
- キーは1つのtailnetに属しています。APIでtailnet名に「-」を指定すると、「このキーが属するtailnet」という意味になります。2つのtailnetの2つのキーは見た目が同じなので、「-」は黙ってキーに従います。
- 2つのtailnetを安全に見分けるには?
- 目で見て判断しないことです。それぞれのキーで一覧表示できるデバイスを比べてください。正しいキーならフリートが見えます。間違ったキーには、そのアカウントが持つ別のものが見えます。
- ツールで「-」というtailnetの別名を使ってよいですか?
- 書き込みをするものには使わないでください。tailnetを明示的に指定すれば、間違ったネットワークのキーは404で失敗します。黙って別のACLを編集することはありません。