AWS 上で「VPN 接続したユーザーだけが見られる Web アプリ」を作りたくて、まずは AWS Client VPN を構築しました。認証には IAM Identity Center のユーザー を使い、Client VPN 側では IAM の SAML identity provider を利用します。AWS Client VPN は IAM Identity Center と SAML で連携する customer managed application として扱われます。 (AWS ドキュメント)
今回は、次の構成を目指しました。
ここはかなり重要です。自分も最初に混乱しました。
Client VPN の SAML 認証で必要なのは、IAM ロールではなく IAM の SAML identity provider です。Client VPN endpoint 作成時にも指定するのは SAML provider ARN です。AWS 公式にも 「IAM ロールを作る必要はない」 と明記されています。 (AWS ドキュメント)
Client VPN は IAM Identity Center のアプリ一覧で最初から専用項目として出るサービスではなく、customer managed application として SAML 2.0 アプリを作る形になります。 (AWS ドキュメント)
セルフサービスポータルを使う場合、Client VPN endpoint 側で self-service portal を有効化する必要があります。また、IdP が複数 ACS URL を扱えない場合は、ポータル用に追加の SAML アプリと追加の IAM SAML provider が必要になります。 (AWS ドキュメント)
セルフサービスポータルは ユーザーベース認証向け です。AWS の管理ガイドでも、mutual authentication を使うクライアントではセルフサービスポータルは利用できない とされています。 (AWS ドキュメント)
今回の流れは次のとおりです。
まずは IAM Identity Center 側にユーザーとグループを用意します。すでに外部 IdP と連携している場合は、そのユーザーを IAM Identity Center で利用してもよいですし、まずは内蔵ディレクトリで小さく始めても十分です。IAM Identity Center は、ユーザーとグループの中央管理基盤として動作し、Client VPN のような SAML アプリにもユーザーを割り当てられます。 (AWS ドキュメント)
IAM Identity Center の Applications から Customer managed を選び、SAML 2.0 アプリ を追加します。自前アプリを作る場合は、IAM Identity Center メタデータと証明書をダウンロードし、相手先サービスプロバイダー情報として ACS URL と Audience を入力します。 (AWS ドキュメント)
Client VPN 本体用のサービスプロバイダー情報は次のとおりです。
http://127.0.0.1:35001urn:amazon:webservices:clientvpn (AWS ドキュメント)この 127.0.0.1:35001 は、AWS 提供クライアントが SAML レスポンスを受け取るためのローカルポートです。フェデレーション認証では AWS 提供クライアント 1.2.0 以降が必要で、対応ブラウザは Safari / Chrome / Edge / Firefox です。 (AWS ドキュメント)
セルフサービスポータルを使う場合、ユーザーはポータルにブラウザでアクセスし、認証後に AWS VPN Desktop Client や Client VPN endpoint の設定ファイル を取得できます。ポータルは endpoint 側で有効化しないと使えません。 (AWS ドキュメント)
IdP が複数 ACS URL を扱えるなら、既存アプリにポータル用の ACS URL を追加します。
https://self-service.clientvpn.amazonaws.com/api/auth/sso/saml (AWS ドキュメント)もし IdP が複数 ACS URL を扱えない場合は、ポータル専用の SAML アプリをもう1つ作るのが安全です。AWS 公式もその構成を案内しています。 (AWS ドキュメント)
次に IAM 側で SAML identity provider を作成します。ここで登録するのは、IAM Identity Center 側でダウンロードした SAML metadata です。Client VPN endpoint では、この IAM SAML provider の ARN を指定します。 (AWS ドキュメント)
ここでハマりやすいのが、「IAM ロールが必要なのでは?」という誤解です。ですが、Client VPN の SAML 認証では IAM ロールではなく IAM の SAML provider が必要です。この違いを先に理解しておくとかなり楽になります。 (AWS ドキュメント)
Client VPN endpoint の作成時は、認証方式で Use user-based authentication → Federated authentication を選びます。そして SAML provider ARN に、先ほど作成した IAM SAML identity provider の ARN を指定します。セルフサービスポータル用の SAML provider を分けた場合は、Self-service SAML provider ARN も指定します。 (AWS ドキュメント)
ここで重要なのは、endpoint 作成時点ではまだ使える状態にならないことです。実際に接続できるようにするには、後続で subnet association、route、authorization rule が必要になります。 (AWS ドキュメント)
セルフサービスポータルを使う場合は、Client VPN endpoint で Enable self-service portal を有効化します。有効化後、ユーザーには次のいずれかの URL を案内できます。 (AWS ドキュメント)
https://self-service.clientvpn.amazonaws.com/https://self-service.clientvpn.amazonaws.com/endpoints/<endpoint-id> (AWS ドキュメント)後者のほうが、ユーザーに endpoint ID を入力させなくて済むので実運用では親切です。ポータルには、VPN に接続するときと同じユーザー認証情報でログインします。 (AWS ドキュメント)
endpoint を作っただけでは、VPN クライアントは実際のネットワークに到達できません。少なくとも次が必要です。
特に authorization rule は見落としやすいです。SAML フェデレーション認証を使う場合、Group ID には SAML 属性で渡されたグループ識別子が使われます。つまり、SAML でどのグループ値を返すか と Client VPN 側の認可ルール はセットで考える必要があります。 (AWS ドキュメント)
今回いちばん苦戦したのは IAM Identity Center の属性マッピング でした。
IAM Identity Center のカスタマー管理 SAML アプリでは、追加の SAML attribute mappings が必要です。AWS 公式でも、これらのマッピングによって IAM Identity Center がアプリ向けに正しい SAML assertion を生成すると説明されています。 (AWS ドキュメント)
要するに、属性マッピングは
「アプリ側が期待する属性名に対して、IAM Identity Center のどのユーザー属性を渡すか」
を決める設定です。たとえば AWS は、アプリ側の Username に IAM Identity Center の email をマッピングする例を示しています。 (AWS ドキュメント)
Client VPN の SAML 認証では、NameID をメールアドレス形式にする前提で設計するのが安全です。少なくとも、Client VPN では SAML レスポンスに属性が必要で、ローカルクライアントがブラウザ連携で認証を受け取ります。構成例としてもメール属性を主軸に組むのが最も安定します。 (AWS ドキュメント)
Client VPN の authorization rules でグループ制御をしたいなら、SAML 側でグループを識別できる属性を返していること が前提です。AWS 公式でも、Group ID は SAML attribute value に対応すると書かれています。ここがずれていると、ログインできても目的の CIDR にアクセスできません。 (AWS ドキュメント)
ここはかなり危険です。
ユーザー同期側の属性マッピング と、アプリ向け SAML assertion の属性マッピング は別物です。今回 Client VPN で必要なのは後者、つまり アプリに何を返すか の設定です。 (AWS ドキュメント)
Client VPN 本体用の ACS は設定したのに、セルフサービスポータル用 ACS を忘れると、VPN クライアントでは動くのにポータル側だけ失敗する 状態になりやすいです。 (AWS ドキュメント)
これは AWS 提供クライアントが TCP 35001 を使って SAML 応答を受けるためで、端末側でそのポートがブロックまたは別プロセスに使用されていると発生します。証明書や VPC よりも前に、まず ローカル端末のポート競合 を疑うべきエラーです。 (AWS ドキュメント)
これは Client VPN では典型的で、split-tunnel / full-tunnel の設計、0.0.0.0/0 の route、関連付け subnet 側の NAT / IGW のどれかが不足しているケースが多いです。VPN 接続成功とインターネット到達性は別問題として切り分けたほうが早いです。 (AWS ドキュメント)
AWS Client VPN を IAM Identity Center ユーザーで運用する場合は、
「Identity Center のカスタマー管理 SAML アプリ」→「IAM SAML identity provider」→「Client VPN endpoint」
の順に考えると理解しやすいです。 (AWS ドキュメント)
今回の要点を最後にまとめます。
これから同じ構成を作る人は、「ロールではなく SAML provider」 と 「属性マッピングは最後ではなく最初に設計する」 この2点だけでも先に意識しておくと、かなりハマりにくくなるはずです。 (AWS ドキュメント)