概要 — 何をするものか
InfraGuard には 2つの認証プレーン があります。
- Web コンソール = セッションログイン。 運用者が
login_id+passwordでサインインすると、AuthControllerが独自のセッションを作成します。以降、すべてのコンソールページはinfr.authミドルウェア(InfrAuth)を通過し、セッションを検証したうえで リクエストごとにユーザーのレベル・氏名・言語をデータベースから読み直し、セッション側の写しを同期させます。 - 外部取り込み API = ステートレスな API キーのベアラー認証。 外部アプリがインシデント・バックアップ結果・セキュリティスキャンを送信するときは、セッションではなく API キートークン(
Authorization: Bearer …またはX-Infr-Api-Key)を使い、infr.apikeyミドルウェア経由で認証します。セッションも CSRF もありません。
主な特徴は次のとおりです。
- セッション再同期 — 管理者がユーザーのレベル・氏名・言語を変更した場合、再ログインなしで 次のリクエストから 反映されます。
- URL レベルでの強制 — メニュー項目を隠すだけでは不十分です。
/security・/backup・/adminといったルートグループは、infr.level:Nミドルウェアによって URL 上で直接、最小レベルを強制します。 - 破壊的な操作 = レベル再確認 + 監査 — ブロック、復元、設定変更などは、書き込みレベルのゲート、
infr_audit_logへの記録、UI 上の確認によって保護されます。
こんなときに使う
- 初めてコンソールにサインインするとき、あるいは突然
/loginに戻されてしまい、その理由を知りたいとき。 - 外部の Laravel アプリを インシデント取り込み API や バックアップ結果の連携 につなぐにあたり、どのヘッダーが認証に使われるかを知りたいとき。
- 管理者がレベル・氏名・言語を変更したあと、なぜ再ログインが不要なのかを説明する必要があるとき。
画面構成
ログイン画面(/login)は1枚のシンプルなカードです。
| 要素 | 説明 |
|---|---|
| ブランド · タグライン | Infra**Guard** ロゴ +「統合インフラ運用・防御・復元力コンソール」 |
| ログインID | login_id の入力欄。autocomplete=username、自動フォーカス |
| パスワード | password の入力欄 + 目のアイコンによる表示/非表示の切り替え |
| エラーバナー | 失敗時:「ログイン情報が一致しません。」 |
隠しフィールド next |
ログイン後の戻り先パス(/ で始まる必要があります) |
| 送信ボタン | 「ログイン →」 |
ログインフォームには標準の Blade
@csrfトークンが含まれます。コンソールはセッション + CSRF で保護されており、UI 上で別途ベアラートークンを求めることはありません。
使い方
サインインする
/loginを開きます(すでにサインイン済みの場合は/にリダイレクトされます)。Login IDとPasswordを入力します。- 入力検証:
login_idは最大60文字、passwordは4〜120文字。
- 入力検証:
- ログイン をクリックします。サーバーは
infr_userからlogin_id+is_close=0でアカウントを探し、パスワードを検証します。 - 成功するとセッションが再生成され(
session()->regenerate())、next(または/)へ送られます。
ログインに成功すると、次の セッションキー が設定されます。
| セッションキー | 値 |
|---|---|
infr_user_id |
infr_user.id(認証済みかどうかの判断基準) |
infr_login_id |
ログイン ID |
infr_user_level |
user_level(整数) — RBAC レベル |
infr_name |
表示名 |
infr_lang |
表示言語(既定は ko) |
あわせて last_log 列に現在時刻が記録されます。
サインアウトする
- 上部バーのユーザードロップダウンにある ログアウト 項目(または
POST /logout)を使います。 - サーバーは
infr_user_idを破棄し、セッションを無効化し、CSRF トークンを再生成して/loginへリダイレクトします。
セッションの有効期間とリクエストごとの再同期
すべてのコンソールページは infr.auth(InfrAuth)を通過し、リクエストごとに次を実行します。
- セッションの
infr_user_idでユーザーを読み直します(ホットパスのため最小限の列のみ:id · login_id · name · email · user_level · role_id · team_id · lang · avatar · is_close)。 - アカウントが存在しない、または
is_close=1(無効化済み)の場合は、セッションを破棄して/loginへリダイレクトします(JSON 要求には 401 を返します)。 infr_user_level·infr_name·infr_langを DB の値で上書き します — そのため管理者によるレベル・氏名・言語の変更は、再ログインなしで次のリクエストから反映されます。- ユーザーモデルを
infr_userリクエスト属性に格納し、app()->setLocale()で表示言語を設定します。 OpsPolicy::markPresence()を呼び出して プレゼンス を記録します(運用ポリシーの省エネモードが「いまコンソールを使っている運用者がいる」と判断して DB 収集を制御するために使います — 運用ポリシー を参照)。
セッションの有効期間は SESSION_LIFETIME(既定120分)に従います。
コンソールのログインに「ログイン状態を保持する」チェックボックスはありません。セッションは上記の有効期間だけ維持され、期限が切れたら再度サインインする必要があります。
外部取り込み API の認証(ベアラーキー)
外部アプリが /api/v1/* に送信する際は、API キー で認証します(ステートレス — セッションも CSRF もありません)。
| 方式 | ヘッダーの例 |
|---|---|
| ベアラー | Authorization: Bearer YOUR_KEY |
| 独自ヘッダー | X-Infr-Api-Key: YOUR_KEY |
動作は次のとおりです。
- サーバーは受け取ったトークンを ハッシュ に変換し、
infr_api_key.key_hash(有効なキーのみ)と 一定時間で(定数時間比較で) 照合します。平文のキーは保存されません。 - キーごとに 毎分120リクエスト のレート制限があります。超過すると
429 rate_limitedとRetry-Afterヘッダーが返ります。 - 呼び出しのたびに
last_used_at·last_used_ip·use_countが記録されます。
主なエンドポイント:
# 疎通確認/キーの確認
curl -sS https://infraguard.example.com/api/v1/ping \
-H "Authorization: Bearer YOUR_KEY"
# インシデントの自動登録(重複排除あり · source=pulse)
curl -sS -X POST https://infraguard.example.com/api/v1/incidents \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"NPE in checkout","fingerprint":"abc123","severity":"crit"}'
キーの発行・失効と連携コードのコピーは 管理 ▸ APIキー で行います(平文のキーは 発行時に一度だけ 表示されます)。
ステップアップ — 破壊的な操作を守る
ブロック、解除、復元、設定変更といったリスクのある操作は、パスワードの再入力ではなく 次の3つの防御で保護されます。
- レベルの再確認 — 書き込み操作には少なくとも書き込みレベル(2以上)、管理操作には管理者(10)が必要で、サーバー側で再検証されます。
- 監査ログ — 変更前後の値に加え、実行者と IP が 監査ログ(
infr_audit_log)に記録されます。 - UI 上の確認 — 確認ダイアログ(ステップアップ)が操作の前に入ります。
データソース
| オブジェクト | 用途 |
|---|---|
infr_user |
運用者アカウント。列:login_id · password · user_level · name · email · lang · is_close · role_id · team_id · last_log · avatar |
| セッションストア(Redis) | infr_user_id などのセッションキー(REDIS_PREFIX は infr_) |
infr_api_key |
取り込み API キーの ハッシュ(key_hash) · is_active · use_count · last_used_at/ip |
infr_audit_log |
破壊的・セキュリティ操作の監査証跡 |
infr_user.password列がログ・URL・Cookie に出ることはありません。API キーの平文は発行時にのみ表示され、データベースにはハッシュだけが保存されます。
アクセス権限
/login·/logout— 誰でもアクセスできます(ゲスト)。- コンソール全体 — 有効なセッション(
infr.auth)が必要です。セッションがない場合、ページ要求は/loginにリダイレクトされ、AJAX 要求は401 unauthenticatedを受け取ります。
URL レベルのゲート(ログイン後に評価されます):
| 領域 | ミドルウェア | 最小レベル |
|---|---|---|
| 一般コンソール(概要 · インフラ · 資産の閲覧) | infr.auth |
ログインのみ(1) |
/security · /backup |
infr.level:2 |
2 |
/admin |
infr.level:10 |
10 |
/horizon · /pulse |
infr.admin |
10 |
| 開発セクション | infr.dev |
9 |
レベルの区分:demo=1 · staff=5 · admin=10。方針の全体は アクセスレベル を参照してください。
トラブルシューティングと FAQ
ログインしても /login に戻されてしまいます。
セッション Cookie が保存されていない(ドメインや SESSION_DOMAIN の不一致、あるいは HTTPS 専用の Cookie を HTTP で配信している)か、アカウントが is_close=1(無効化)になっています。管理者にアカウントの状態を確認してもらってください。
「ログイン情報が一致しません。」と表示されます。
login_id の打ち間違い、パスワードの誤り、または無効化されたアカウント(is_close=1)です。セキュリティ上、どれが原因かはメッセージに示されません。
アカウントがログインできません。 パスワードの誤りまたはアカウントが無効化されている可能性があります。管理者が ユーザーと役割/チーム でパスワードをリセットしてください。
ログインはできますが /admin を開けません。
レベルが10未満です。/admin は infr.level:10 で守られているため、管理者しか到達できません。同様に /security と /backup にはレベル2以上が必要です。
AJAX 呼び出しが 401 を返します。
コンソールのセッションが期限切れです。ページを再読み込みして、もう一度サインインしてください。JSON 要求にはリダイレクトではなく {"error":"unauthenticated"} の 401 が返ります。
管理者にレベルを上げてもらいましたが、反映されません。
InfrAuth はリクエストごとにセッションを再同期するため、次の画面遷移から 反映されます — 再ログインは不要です。すぐに反映したい場合は再読み込みしてください。
メニューや UI が想定と違う言語になっています。
表示言語は infr_user.lang(セッションの infr_lang)に従い、リクエストごとに再同期されます。多言語設定 で変更できます。
API が 401 invalid_api_key / 429 rate_limited を返します。
無効なキーや打ち間違いは 401、毎分120リクエストを超えると 429(+ Retry-After)になります。APIキー でキーの状態を確認し、送信の間隔を落としてください。
関連項目
- アクセスレベル —
user_level↔min_req、demo/staff/admin の区分 - 役割とチーム — 役割のスコープとチームの所有権
- ユーザーと役割/チームの管理 — アカウントの作成、パスワードのリセット、無効化
- APIキー — 取り込み API キーの発行と連携コード
- 多言語設定 — 表示言語とロケールのフォールバック
- 監査ログ — 破壊的な操作の追跡
