コンテンツにスキップ

セキュリティ

NMS は、監視対象ネットワークの鍵を握っています。SNMP コミュニティ、SNMPv3 の認証情報、ポーリング 先サービスの API キーです。Yagra のセキュリティモデルはその事実から出発し — 認証情報は保存時に 暗号化し、決してログに出さず、ワイヤ上では届く範囲を厳しく絞る — そのうえで残りの攻撃面も小さく 保ちます。非 root のコンテナ、内部専用のストア、検証済みの外向き宛先、そしてすべての変更に対する 監査証跡です。

監視用の認証情報は保存時にエンベロープ暗号で保護されます。各シークレットはそれぞれ専用の データ鍵で暗号化され、データ鍵はマスタ鍵(KEK)でラップされます。データベースが保持するのは 暗号文だけです — データベースのダンプだけでは認証情報は何も明らかになりません。

KEK はマウントしたファイルであり、環境変数の値ではありませんYAGRA_KEK_FILE が運ぶのは鍵 そのものではなくパスなので、シークレットが docker inspect やプロセス環境から露出することは ありません。同梱の compose ファイルは専用ボリュームに一度だけ鍵を生成し、コアに読み取り専用で マウントします。

永続的な KEK がない場合、コアは一時的な開発用鍵にフォールバックします。この鍵は再起動の たびに再生成され、コアは強い警告を出します。その鍵で暗号化して保存した認証情報は再起動を 越えられません。本番をフォールバックのまま運用しないでください。

認証情報は決してログに出ず、API から返されることもありません — ログ、API レスポンス、 メトリクスのラベルのいずれからも伏せられます。

3 つのコンテナはいずれも非 root ユーザーで動作します。

イメージ ユーザー 権限
yagra-core uid 10001 通常のプロセス以上のものはなし
yagra-poller uid 10002 NET_RAW のみ — raw ソケットの ICMP のための、バイナリに付与したファイルケーパビリティ
yagra-web nginx uid 101 非特権の nginx。コンテナポート 808080 ではありません)で待ち受け

CAP_NET_RAW を持つのはポーラーだけです。ICMP による死活監視に raw ソケットが必要だからで、 それ以外のコンテナには与えません。その結果として、非特権のポーラーは 1024 未満のホストポートに バインドできません。だからこそパッシブリスナーは高番号のコンテナポート(15141162)を使い、標準の低番号ポートは手前でマップまたはリダイレクトします — ポートとファイアウォールを参照してください。

5 つのストア(PostgreSQL、Redis、VictoriaMetrics、VictoriaLogs、ClickHouse)と NATS バスは、 すべて内部の Docker ネットワーク上にあります。同梱の compose ファイルはどれもこれらを公開せず、 スタックの外からこれらに到達する必要も一切ありません — そのままにしてください。

バスには特に注意が必要です。ジョブメッセージは平文のデバイス認証情報を運びます — コアから、 それを使うポーラーへ向けて。単一ホスト上ならこのトラフィックが内部ネットワークを出ることは ありません。リモート拠点のポーラーを運用し始めた瞬間から、バスのポートを公開してよいのは同梱の TLS + 認証の設定を整えた場合に限られます — 信頼境界をまたいで平文の NATS :4222 を晒しては いけません。

さらなるハードニングとして、Yagra は各ポーラーがバスに何を要求できるかまでスコープできます。 NATS Auth Callout を有効にすると、コアがバスの認可サービスとして動作し、接続してくる ポーラーごとに、自分の割当サブジェクトと自分のプールのトラフィックだけに限定した短いスコープの 識別情報を発行します。侵害されたポーラーは他拠点のジョブを購読できなくなり — したがって他拠点の 認証情報を受け取ることもできません。設定方法とリモートポーラーのアーキテクチャは 分散ポーリングで扱います。

WebUI はホストポート 443 の HTTPS で提供され、平文のリスナーはありません。 WebUI が運ぶもの — ログインパスワード、Bearer のセッショントークン、暗号化ストレージへ向かう途中のデバイス認証情報 — は、以前は既定で平文のままネットワークを渡っていました。今は、何もしなくても手に入る側が安全な 構成です。

正本の証明書は PostgreSQL に保管され、他のすべての秘密と同じ KEK でエンベロープ暗号化されます。コアが それを web コンテナの読むボリュームへ実体化します。何も取り込んでいない初回起動では、コアが ループバックとコンテナのホスト名を対象とする自己署名証明書を生成するため、ブラウザは警告を 出し、名前も一致しないのが普通です(利用するアドレスをコンテナ内から知る術はありません)。 設定 ▸ TLS 証明書で正式な証明書を取り込むか、実際に使う名前を指定して自己署名証明書を再生成して ください。秘密鍵が API から返ることはありません。証明書はダウンロードできるので、Prometheus の ca_filecurl --cacert、OS のトラストストアに渡せます。取り込んだ証明書は何も再起動せずに 数秒で有効になり、システムヘルスが有効期限を報告します(Prometheus のゲージ yagra_web_tls_expires_in_days にも出ます)。

手前の外部リバースプロキシやロードバランサが既に HTTPS を終端している場合は YAGRA_WEB_TLS=off を設定してください。平文のリスナーに戻る手段はこれだけです。

コア自身の API ポート(8080)は平文のまま、LAN に公開のままです。 これは見落としではなく 意図した順序です。信頼されていない証明書を導入するのと同じアップグレードでこのポートを閉じると、 Prometheus の scrape も API スクリプトも一斉に落ち、原因が 2 つ重なって切り分けできません。まず それらのクライアントを、信頼できる証明書のある https://<host>/api/v1/… へ移し、そのうえで YAGRA_API_BIND=127.0.0.1 を設定してポートをネットワークから外してください。現在どちらの 状態かは設定 ▸ TLS 証明書に出ます。8080 を素のまま信頼できないネットワークへ公開しないでください。

対話的なアクセスはセッションベースです。POST /api/v1/auth/login がユーザー名とパスワードを Bearer のセッショントークンと交換し、以後の REST リクエストはすべてそれを提示します。

  • 総当たり対策。 ログインエンドポイントは、失敗が続くとアカウント単位で指数的にロックアウト し、加えて全体の試行レート上限も適用します — パスワード推測の連打と、強制されるパスワード ハッシュ計算の CPU コストの両方を抑えます。
  • 有効期限。 セッションはアイドル期間と絶対寿命の両方で期限切れになります。
  • 失効。 ログアウトするとトークンはサーバー側で失効します。ユーザーの無効化・降格・削除・ パスワードのリセットは、そのアカウントのアクティブなセッションを即座に無効化します — 侵害された アカウントへの管理者の対応が、発行済みのトークンをただちに断ち切ります。
  • 初回起動。 YAGRA_ADMIN_PASSWORD が未設定の場合、コアは admin 用のランダムな一度限りの ブートストラップパスワードを生成してログに一度だけ出力します — 周知の既定パスワードは存在 しません。

高可用性ペアでは、マウントする署名鍵(YAGRA_SESSION_KEY_FILE)を任意で設定することで、 セッションが署名付きのステートレストークンになります。ペアのどのコアでも検証でき、コアの 再起動やフェイルオーバーを越えて有効なので、フェイルオーバーで全員がログアウトされることは ありません。失効は引き続き強制されます — 失効したトークンは追跡され、どのコアでも拒否されます。

非対話的なクライアント向けに、管理者は設定 ▸ API トークンから長期有効な API トークン (yat_ プレフィックス)を発行できます。トークンを縛るものは次のとおりです。

  • 使える入口。 トークンは MCP エンドポイント(/mcp)、REST API、あるいはその両方に 届きます。どれになるかは発行時の指定次第です。この項目が存在する前に作られたトークンは mcp のみを持つため、アップグレードで既存の認証情報の権限が広がることはありません。
  • 所有アカウント。 実効ロールはトークン自身のロールと所有者の現在のロールの低い方なので、 降格すれば直ちに狭まり、アカウントを無効化・削除すれば失効します。無人のトークンは サービスアカウント(サインインできない機械の識別子)に所有させてください。認証情報が個人に 依存しなくなり、1 つのスイッチでそれが所有するすべてを止められます。
  • ロールによらずトークンにできないこと: ユーザー管理と、サインイン中のアカウントを特定する エンドポイントの利用。前者が特に重要です。自身の後継を発行できる認証情報は元の失効を生き延びて しまい、それはまさに退職処理が見落とすものだからです。
  • 任意の有効期限と、同じ画面からのいつでもの失効。
  • 生のトークンが表示されるのは作成時のちょうど 1 回だけで、保存されるのはハッシュのみです。
  • トークンはフリート全体をスコープとします。グループを限定したトークンは発行できません。
  • 発行・失効、およびトークンで行われたすべての書き込みは監査ログに記録され、所有アカウントと トークンの両方(svc-ci (token:grafana))で帰属されます。

オペレーターが Yagra に URL を指定できる機能はいくつかあり、そのいずれもがリクエストの実際の 行き先を検証します。

  • URL 監視は、HTTP(S) 以外のスキームと、ループバック・リンクローカル(クラウドのメタデータ アドレス 169.254.169.254 を含む)など、権限昇格につながりうる到達すべきでない宛先を拒否します。 検証は設定時ポーリング時の両方で行われます(その間に DNS が変わりうるためです)。 リダイレクトも同じポリシーで 1 ホップずつ再検証されます。通常のプライベートアドレス空間は 許可されたままです — プライベートなインフラを監視することこそ NMS の目的だからです。
  • Webhook の通知先も設定時に同じ方法で検証され、配信時に再検証されます。外向きの クライアントはリダイレクトを一切追いません。
  • PagerDuty への配信は公式のイベントエンドポイント(events.pagerduty.com / events.eu.pagerduty.com)に HTTPS のみでピン留めされます — 紛らわしいホストや平文 HTTP の URL は設定時に拒否されます。Jira Service Management も同様に api.atlassian.com へピン留め されます。
  • Cisco Meraki 監視は厳密に読み取り専用です。クライアントは GET リクエストしか発行せず、 リダイレクトを追わず、ページングされたリクエストのたびにホストを再検証します。

状態を変更する API 操作はすべて — ノードの作成、認証情報のローテーション、アラートの確認(ACK)、 トークンの発行、メンテナンスウィンドウの開始 — 実行したユーザー、変更内容、日時とともに記録され ます。MCP の書き込みツールも、トークンの識別情報のもとに同じ証跡を残します。

ログは設定 ▸ 監査ログで閲覧でき、閲覧には監査権限が必要です。既定でこれを持つのは Admin(管理者)ロールだけです。

データがシステムの外に出る経路

Section titled “データがシステムの外に出る経路”

何も設定していない新規インストールは、(イメージの取得を除き)外向き通信を一切行いません。 外向きの経路はすべてオプトインで、機能単位です。

  • 通知チャネル — Webhook、メール(SMTP)、PagerDuty、Jira Service Management — は、設定した エンドポイントへアラートの内容を送ります。
  • 転送は、受信した syslog・トラップ・フローを設定した外部コレクタへ中継し、正規化した イベント/フローの行を BigQuery へストリーミングすることもできます。
  • AI 根本原因分析既定で無効です。プロバイダを設定しなければクライアントも認証情報も 外向き通信も存在しません。有効にすると、インシデントのコンテキスト(認証情報は決して含まれ ません)が設定した 1 つのプロバイダへ送られます。Vertex AI を選んだ場合は自分の GCP プロジェクト 内に留まります。
  • MCP のツール結果 — インベントリ、ステータス、メトリクス、イベント — は、/mcp に接続した AI クライアントへ渡ります。MCP を有効にするということは、監視データへの読み取りアクセスに ついてそのクライアントを信頼するということです。

完全な一覧 — すべての宛先、プロトコル、そしてどのプロセスが外へ接続するか — は ポートとファイアウォールの外向き通信の表にあります。

脆弱性の疑いは GitHub リポジトリから報告してください。 修正が用意される前に、公開 issue でエクスプロイトの詳細を公表することはお控えください。