社内の運用担当だけが使う管理の画面を、IPアドレス制限とBASIC認証で守る構成は長く使われてきた。 運用コストがほぼゼロで、配信の手前だけで完結するからである。 行き詰まるのは2点で、在宅を許すとIPアドレスで絞れなくなり、共有のパスワードでは1人だけを止められない。
移行先はCognito認証とクライアント証明書だが、これは1手ではない。 制限は独立した2つの軸でできており、移行は軸を1つずつ動かす2手になる。 そして2手の重さが違う。片方はSPAとAPIの改修を伴い、もう片方は配信の設定で済む。
本稿では、2つの軸の整理、2手それぞれが何を埋めて何を要求するか、組み合わせの一覧、 そして切り替えた先でセキュリティ管理者が見ることになる対象を示す。
1. 制限は2つの軸でできている
どちらの軸にも「制限しない」という選択がある。 前段で本人性を確かめなければ、アプリケーション自身の認証に委ねることになる。
到達範囲の2つの方式は、互いに排他ではない。 IPアドレス制限はHTTPの要求に対する評価、クライアント証明書はTLSの握手の段での検証で、効く層が違う。 配信の設定に両方を並べられ、重ねるとANDとして働く。固定IPから来て、かつ証明書を持つ端末だけが通る。
到達範囲の方式は、どちらも「誰か」を見ていない。 IPアドレス制限は回線を、クライアント証明書は秘密鍵を持つ端末を見ている。 その回線に繋がる端末なら誰でも通り、その端末を他人が使っても通る。
本人性の方式は、どこから来たかを見ていない。 BASIC認証はパスワードの一致だけ、Cognito認証は利用者だけを見る。
2つは互いの代替にならない。だから足し算になる。 ネットワークの内側にいることが相手の身元を示さないのと同じ理屈である(プライベートネットワークの再考)。
SaaSの利用者が使う画面は、前段にどちらの関門も置けない。 理由は3章で述べる。 アプリケーション自身の認証と干渉するため、両方の軸が「制限しない」に固定され、身元はアプリケーション側で確かめることになる。 動かせるのは管理の画面だけである。
2. いまの構成で何が起きているか
IPアドレス制限とBASIC認証は、互いの穴を部分的に塞いでいる。 IPアドレス制限が到達できる相手を減らしてBASIC認証を総当たりから守り、 BASIC認証が「回線にいれば誰でも」をパスワードを知っている人に絞る。
残る穴は、どちらも識別の単位を持っていないことから来る。
2つ重ねても識別の単位は増えない。どちらの方式も「個人」を持っていないからである。
3. 手① 本人性を替える(BASIC認証 → Cognito認証)
得られるのは識別の単位である。誰が入ったかが残り、利用者を無効化すれば1人だけ止められ、多要素認証も足せる。
代償はSPAとAPIの改修である。ここが移行の重い方になる。 前段の関門は、画面のドキュメントのリクエストと、SPAが叩くXHRを区別しない。 区別しないことが、HTTPの層で判定する方式では問題になる。
替える前のBASIC認証にも、同じ層に起因する制約があった。
BASIC認証は Authorization ヘッダーを占有するため、APIが Authorization: Bearer を使う設計とは共存できない。
APIを別オリジンに置くと、CORSのプリフライトが資格情報を含めない決まりのため、前段が401を返して本リクエストに進めない。
APIがセッション切れで401を返すと、ブラウザのネイティブな認証ダイアログがSPAの操作中に出る。ログアウトもできない。
SaaSの画面に前段の関門を置けないのは、この干渉が理由である。
アプリケーション自身が認証を持っているため、前にBASIC認証を置けば Authorization が衝突し、
Cognito認証を置けば二重ログインになる。証明書を配れないからではない。
4. 手② 到達範囲を替える(IPアドレス制限 → クライアント証明書)
手①を終えても、IPアドレス制限が残っている限り在宅からは通れない。 では外せばよいかというと、外すと認証のエンドポイントが全世界に公開される。 総当たりや脆弱性の試行がアプリケーションまで届く。IPアドレス制限はここを塞いでいた。
その穴を、場所ではなく端末で埋めるのがクライアント証明書である。 置き換える相手はIPアドレス制限であって、Cognito認証ではない。
ただし両立できないから置き換えるのではない。 1章のとおり、両方を同時に有効にできる。 それでも替えるのは、場所に依存することをやめるのが目的だからである。 IPアドレス制限を残したままでは、在宅から通れないという制約がそのまま残る。
段階的に移すなら、この性質を使える。 証明書を配り終えるまで両方を有効にし、配り終えてからIPアドレス制限を外す。 配布が済んでいない端末は、その間も従来どおり事務所から通れる。
この手はアプリケーションに影響しない。 TLSの層、つまり接続の確立時に判定されるため、ドキュメントもXHRも同じ条件で通り、 リクエストのヘッダーを消費しない。手①と重さが違うのはここである。
例外が2つある。 証明書の情報(通し番号、発行者、Subject、有効期間)をオリジンへ渡す場合は、 オリジンリクエストポリシーに明示的に挙げる必要があり、他の目的で必須のヘッダーと枠を取り合うことがある。 また、ブラウザの証明書選択はネイティブのダイアログでアプリケーションから制御できないため、 APIを別オリジンに置く場合は挙動を確かめる。
採用の前に効く制約も4つある。
失効の確認も組み込みではない。 CloudFront は Trust Store に対して証明書を検証するが、失効したかどうかは見ない。 失効させた通し番号を保持し、接続時に動く関数が照合する構成が案内されている。 発行と失効をどう回すかはクライアント証明書の発行と失効を運用に載せるに分けて書いた。
5. 組み合わせの一覧
どちらの軸にも「制限しない」があり、到達範囲は重ねられる。主なものを並べると、それぞれの位置づけがはっきりする。
クライアント証明書を足しても、個人の列は埋まらない。 証明書は端末を示すだけで、貸与端末を他人が使えば通る。 逆に、Cognito認証を足しても端末の列は埋まらない。認証情報を奪われれば、どの端末からでも入れる。 両方を埋めたいから、組み合わせになる。
本人性を前段に置かない選択もある。 アプリケーション自身が認証を持っているなら、前段は到達範囲だけを受け持ち、個人はアプリケーション側で確かめる。 前段がヘッダーもCookieも使わないため、SPAとAPIの作りに制約をかけない構成になる。 ただし前段の記録には個人が残らないので、誰が接続してきたかはアプリケーション側のログで追うことになる。
6. 2手の順序
手①を先に進める。識別の単位が無いままでは、到達範囲だけを細かくしても誰が入ったかを追えないからである。 手①はSPAとAPIの改修を伴うため、時間もかかる。
手①だけで止めた状態(IPアドレス制限 + Cognito認証)は、そのまま運用できる。 在宅が通らないという制約は残るが、監査と個別の失効は手に入る。
手②も一度に切り替える必要はない。 到達範囲は重ねられるため、証明書を配りながら両方を有効にしておき、配り終えてからIPアドレス制限を外せる。 この間は在宅から通れないままだが、配布の遅れで誰かが締め出されることはない。 在宅の要求が先に来ると、IPアドレス制限を外す判断になりやすい。 その状態が一覧の「制限しない + Cognito認証」で、ログイン画面が全世界に晒される。 手②は、この判断を迫られる前に用意しておく。
7. セキュリティ管理者が見ておくもの
切り替えの判断と、これらを引き受ける体制は同時に決める(DevSecOpsにおける責務分離)。 軸を1つずつ動かしたときに扱いがどう変わるかと、証明書の台帳は、操作できる画面に置いた。 どちらの軸も「制限しない」状態、つまり公開するページから始まり、絞るたびに誰が通れなくなるかを追える。
アクセス制限の切り替え(運用画面例。AWSに接続しないモック)
8. まとめ
アクセス制限は、強い方式へ進む一本道ではない。 どちらの軸をどこまで動かしたかで、できることと残る穴が決まる。 2手に分けて、それぞれが何を埋めて何を要求するかを把握してから着手する。
