AWS Client VPNの認証をIAM Identity Centerと連携させる。

# はじめに
前回までの記事で`IAM Identity Center`を使った認証設定を行ってきましたが、`AWS Client VPN`でVPN接続する際の認証設定も`IAM Identity Center`の認証で集約することができるため、番外編として`AWS Client VPN`の設定を紹介しながら、`AWS Client VPN`の認証を`IAM Identity Center`と連携させてみようと思います。

- 【前】[IAM Identity Centerを使って複数アカウント管理する。（その４：GHECへのSAML）](https://qiita.com/sakai00kou/items/2a35a58b5dada7e5f285)

# AWS Client VPN運用方法の検討
`AWS Client VPN`でAWSに接続する場合、証明書ベースの認証方法と`Active Directory`やフェデレーション認証によるユーザベースの認証方法があります。

全社的なClient VPN環境を構築する場合は`Active Directory`やフェデレーション認証でユーザ情報を一元管理したほうが良いと思いますが、開発現場などでは会社が複数絡むこともあり、証明書ベースの認証方法とする場合が多いかと思います。

ただ、証明書を使うとなると、どこかで証明書を作らなければならず、仮に自分のPCで作った証明書をVPN接続ユーザに配布するにしても、次に他の人に証明書作成をお願いした場合に環境依存でうまく作成できなかったりする場合も考えられるため、できればあまりやりたくありません。

環境統一のため、証明書作成用のサーバなど準備するというのも大掛かりすぎてこちらもできればやりたくありません。

かと言って、以下のAWSの記事のように`AWS Private Certificate Authority`でプライベートCAを作って証明書を発行するにしても、`AWS Private Certificate Authority`で作成したプライベートCAが存在するだけで月額$400かかるので個人用途としては高くて手が出せません。

- [AWS Certificate Manager による相互認証用のプライベート証明書を使用して Client VPN エンドポイントを作成して接続するにはどうすればよいですか？](https://aws.amazon.com/jp/premiumsupport/knowledge-center/client-vpn-authenticate-private-ca-acm/)

幸い、私は外部からのアクセス用にお名前.comで取得した独自ドメインを持っており、`Route53`にドメイン登録を行っているため、今回は`IAM Identity Center`によるフェデレーション認証と`AWS Certificate Manager`（以下`ACM`）でパブリック証明書を作成する方法で行ってみたいと思います。

# AWS Client VPNの構築
今回始めて`AWS Client VPN`を触ってみるのにちょうどよいハンズオンと、`ACM`を使用した`AWS Client VPN`の方法が書かれた記事と、`IAM Identity Center`を用いた`AWS Client VPN`の記事があったため、ハンズオンの手順に沿いながら、証明書作成の箇所は`ACM`で作成する方法、認証の箇所は`IAM Identity Center`で行う方法で進めてみたいと思います。

- [AWS Client VPN Basic ハンズオン](https://catalog.us-east-1.prod.workshops.aws/workshops/be2b90c2-06a1-4ae6-84b3-c705049d2b6f/ja-JP)
- [ACM で発行したパブリック証明書で Client VPN を構築してみた](https://dev.classmethod.jp/articles/clientvpn-with-acm-public-certificates/)
- [AWS SSO を用いた AWS Client VPN の認証と承認](https://aws.amazon.com/jp/blogs/news/using-aws-sso-with-aws-client-vpn-for-authentication-and-authorization/)

また、今回はドメインの取得方法までは説明しないため、ドメインを取得されていない方は、以下の手順などを参考に独自ドメインを取得してください。

- [EIPを持たずにホスト名でアクセスする](https://qiita.com/sakai00kou/items/41ac618a4fe0a5318f06)

以下手順の目次

- [今回の構成](#今回の構成)
- [ログ出力・証明書の作成](#ログ出力証明書の作成)
    - [ログ出力設定](#ログ出力設定)
    - [パブリック証明書の作成](#パブリック証明書の作成)
- [IAM Identity Center関連の設定](#iam-identity-center関連の設定)
    - [IAM Identity Centerのアプリケーション追加](#iam-identity-centerのアプリケーション追加)
    - [IDプロバイダの追加](#idプロバイダの追加)
- [AWS Client VPNの設定](#aws-client-vpnの設定)
    - [クライアントVPNエンドポイントの作成](#クライアントvpnエンドポイントの作成)
    - [ターゲットネットワークの関連付け](#ターゲットネットワークの関連付け)
    - [承認ルールの追加](#承認ルールの追加)
- [VPNクライアントのセットアップ](#vpnクライアントのセットアップ)
- [VPN接続](#vpn接続)
- [Pingの実施](#pingの実施)
- [Self Service Portal URLのアプリケーションへの紐付け](#self-service-portal-urlのアプリケーションへの紐付け)
    - [AWS Client VPN＆セルフサービスポータル用アプリケーションの編集](#aws-client-vpnセルフサービスポータル用アプリケーションの編集)
    - [セルフサービスポータル画面へのアクセス](#セルフサービスポータル画面へのアクセス)

## 今回の構成
ちょうどパブリックサブネット、プライベートサブネットがそれぞれ2つずつ作成されているので、それらのVPC、サブネットを使いまわし、以下のような構成を組んでみようと思います。

![VPN構成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/8a299319-959b-c6d6-94c6-f43589f19477.png)

## ログ出力・証明書の作成
`AWS Client VPN`の設定を行う前作業としてログ出力の設定とパブリック証明書の作成を行います。

### ログ出力設定
ハンズオンに沿って、VPN接続時のログ出力設定を行っていきます。

`CloudWatch`の画面より、「**ログ**」→「**ロググループ**」の「**ロググループの作成**」から以下のように設定します。

今回はテストなので保持期間は1日としました。

|項目|設定|
|:--|:--|
|ロググループ名|/aws/clientvpn|
|保持期間の設定|1日|
|KMS key ARN|空欄|

上記で作成したロググループ名を選択し、「**ログストリーム**」タブから「**ログストリームを作成**」で以下ログストリームを作成します。

|項目|設定|
|:--|:--|
|ログストリーム名|connection-log|

### パブリック証明書の作成
以下`ACM`画面から「**証明書をリクエスト**」を選択。

![Monosnap_20230312_133728.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/39db583f-0103-a0aa-1519-e9cb75e20e7e.png)

今回はパブリック証明書を使うので、「**パブリック証明書をリクエスト**」を選択し、「**次へ**」で進みます。

![Monosnap_20230312_133808.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/bdb947e9-6a52-9207-f70f-2195f840b407.png)

ドメインは`Client VPN`で接続する際に指定したいドメイン名を指定。（マスクしていますが今回は`vpn.xxxx.xxxx`としました）

検証方法とキーアルゴリズム、また、以下画面では見切れているタグ設定は変更せずに画面右下の「**リクエスト**」を選択します。

![Monosnap_20230312_134105.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/e3963e71-238e-fc8f-7cf0-0680c91219a8.png)

リクエストを行うと、以下の画面が表示されますが、現状はまだ「`vpn.xxxx.xxxx`」と言ったホストは存在しないので、「**保留中の検証**」となりますが、気にせず「**証明書ID**」のIDを選択し、詳細画面に入ります。

![Monosnap_20230312_135114.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/a6b5ccfa-0a00-d2e1-f2a6-96338dcb6a9e.png)

レコードを登録するため、ドメイン項目にある「**Route 53でレコードを作成**」を選択、遷移後の画面でも「**レコードを作成**」を選択して`Route53`で管理しているホストゾーンにレコードを追加します。

もし`Route53`を使っていないようなら、自身のドメインを管理しているDNSサーバに、表示された`CNAME`名と`CNAME`値の`CNAME`レコードを追加してください。

![Monosnap_20230312_135724.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/b9b3a22c-1daa-89a9-041e-0ced02f3d142.png)

![Monosnap_20230312_140006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/346bb5cf-e1c3-9454-29a2-26500a85a690.png)

成功すれば先程「**保留中の検証**」となっていたステータスが「**発行済み**」となり、`Route53`にも`CNAME`レコードが追加されているはずです。

![Monosnap_20230312_142948.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/d35fabbb-4629-184f-72df-023d94269445.png)

## IAM Identity Center関連の設定
VPN接続時の認証を`IAM Identity Center`で行うようにするため、VPN用のSAMLアプリケーションの作成と、IDプロバイダの設定を行います。

### IAM Identity Centerのアプリケーション追加
`AWS Client VPN`の認証を`IAM Identity Center`で行えるようにするため、`IAM Identity Center`の設定からアプリケーションを追加していきます。

今回は、VPN接続用のアプリケーションだけではなく、VPNクライアントやクライアント構成ファイルをダウンロードできるようにするセルフサービスポータル用のアプリケーションも作成しようと思うので、別のアプリケーションとして２つ作成します。

「**IAM Identity Center**」→「**アプリケーションの割り当て**」→「**アプリケーション**」より「**アプリケーションの追加**」を選択します。

![Monosnap_20230315_215848.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/c5623cc7-a4f1-7040-ffb8-77d03a176ff6.png)

「**アプリケーションを選択**」より、今回は「**カスタムSAML2.0アプリケーションの追加**」を選択します。

![Monosnap_20230315_220024.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/9d7b3743-7459-82d0-3474-66c0d2803f13.png)

アプリケーションの表示名、説明については任意の名前を入力、「**IAM Identity Centerメタデータ**」の「**IAM Identity Center SAMLメタデータファイル**」はダウンロードしておきます。

![Monosnap_20230315_190722.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/90b812c0-3f3c-3423-ab92-f10f7cabeaac.png)

「**アプリケーションのプロパティ**」欄はデフォルトのまま空欄とし、「**アプリケーションメタデータ**」は「**メタデータ値をマニュアルで入力する**」を選択した上でそれぞれ以下の値を固定値で入力します。

尚、`Client VPN`接続用設定とセルフサービスポータル用設定で「**アプリケーションACS URL**」の指定が変わってきます。

セルフサービスポータルを使用しない場合は「**Client VPN接続用設定**」のみで問題ありませんが、例えば外部の方にもVPNを使わせたい場合や、接続人数が多い場合はセルフサービスポータルを有効にしたほうが手間が減るので、導入するシステムによって使い分けてください。

|項目|Client VPN接続用設定|セルフサービスポータル用設定|
|:--|:--|:--|
|アプリケーションメタデータ|メタデータ値をマニュアルで入力する|メタデータ値をマニュアルで入力する|
|アプリケーションACS URL|http://127.0.0.1:35001|https://self-service.clientvpn.amazonaws.com/api/auth/sso/saml|
|アプリケーションSAML対象者|urn:amazon:webservices:clientvpn|urn:amazon:webservices:clientvpn|

![Monosnap_20230315_220222.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/0a24e567-cf24-d690-c318-7a0c3e880d5f.png)

作成したアプリケーションの「**アクション**」から「**属性マッピングを編集**」を選択します。

![Monosnap_20230315_220837.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/f96323bf-f56d-853f-ec62-466e70c88653.png)

今回は以下２つの属性マッピングを設定する必要があるため、以下の通りに設定します。

属性マッピングの設定はClient VPN接続用設定もセルフサービスポータル用設定も同一なので、同じように設定してください。

|アプリケーションのユーザー属性|この文字列値またはIAM Identity Centerのユーザー属性にマッピング|形式|
|:--|:--|:--|
|Subject|${user:email}|emailAddress|
|memberOf|${user:groups}|unspecified|

![Monosnap_20230315_221255.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/059e2954-59c2-92c1-9bf2-91f43450102c.png)

「**ユーザーを割り当て**」より、作成したアクションに割り当てるユーザ・グループを指定します。

セルフサービスポータルを使用する場合はClient VPN接続用設定と同じユーザ・グループを割り当てるようにしてください。

今回は先程の属性マッピングの設定でグループIDを渡すようにしているため、ユーザではなくグループ単位で選択します。

![Monosnap_20230315_221532.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/706f8ebc-5645-7906-678f-d3d8f608b8e0.png)

### IDプロバイダの追加
前回、外部AWSアカウントとの連携でも行ったIDプロバイダの追加を行います。

今回は`AWS Client VPN`も`ACM`も`IAM Identity Center`もルートアカウントで行おうと思うので、IDプロバイダもルートアカウントで作成しようと思います。

設定方法は前回の記事の「**IDプロバイダの追加（外部組織）**」と同様となるので、表のみ以下に記載します。

また、IDプロバイダはClient VPN接続用、セルフサービスポータル用それぞれで別々のIDプロバイダを用意する必要があるため、セルフサービスポータルも使用する場合は２種類設定します。

|項目|Client VPN接続用設定|セルフサービスポータル用設定|
|:--|:--|:--|
|プロバイダのタイプ|SAML|SAML|
|プロバイダ名|任意（今回はIdentityCenterSAML-VPN）|任意（今回はClientVPN-SelfServicePortal）|
|メタデータドキュメント|Client VPN接続用アプリケーションでダウンロードしたメタデータドキュメントを選択|セルフサービスポータル用アプリケーションでダウンロードしたメタデータドキュメントを選択|

## AWS Client VPNの設定
以下よりいよいよ`AWS Client VPN`自体の設定を行っていきます。

### クライアントVPNエンドポイントの作成
クライアントからのVPN接続を終端するクライアントVPNエンドポイントを作成します。

それぞれ自身の環境に合わせて設定値を調整してください。

セルフサービスポータルを使用する場合は「**セルフサービスポータルを有効化**」と「**セルフサービスSAMLプロバイダーARN**」の指定を忘れないように設定してください。

|項目|設定|
|:--|:--|
|名前タグ|任意（今回はClientVPN-Endpoint-Test）|
|説明|任意|
|クライアントIPv4 CIDR|任意（今回は100.64.0.0/22）|
|サーバー証明書ARN|先程ACMで作成した証明書ARN|
|認証オプション|ユーザーベースの認証を使用|
|ユーザーベースの認証オプション|フェデレーション認証|
|SAMLプロバイダーARN|先程作成したIDプロバイダARN（今回はIdentityCenterSAML-VPN）
|セルフサービスSAMLプロバイダーARN|先程作成したIDプロバイダARN（今回はClientVPN-SelfServicePortal）|
|クライアント接続のログの詳細を有効化|有効化|
|CloudWatch Logsのロググループ名|今回は`/aws/clientvpn`|
|CloudWatch Logsのログストリーム名|今回は`connection-log`|
|クライアント接続ハンドラーを有効化|無効|
|DNSサーバ|空欄|
|トランスポートプロトコル|UDP|
|スプリットトンネルを有効化|有効化|
|VPC ID|VPN接続を行うVPCを選択|
|セキュリティグループID|空欄|
|VPNポート|443|
|セルフサービスポータルを有効化|セルフサービスポータルを使用する場合は有効化|
|セッションタイムアウト（時間）|24|
|クライアントログインバナーを有効化|無効|
|タグ|デフォルトのまま|

また、セルフサービスポータルを有効にしていない場合は、クライアントVPNエンドポイントの画面の「**クライアント設定をダウンロード**」からクライアント構成ファイルをダウンロードしてVPN接続ユーザに配布してください。

![Monosnap_20230318_133057.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/d867cbbe-6a82-c7b3-0a3a-a8c66fd7e78a.png)

### ターゲットネットワークの関連付け
作成したクライアントVPNエンドポイントをどのセグメントに紐付けるかを設定します。

先程作成したクライアントVPNエンドポイントの「**ターゲットネットワークの関連付け**」タブから「**ターゲットネットワークを関連付ける**」選択します。

今回は既存ですでに作成しているパブリックサブネット２つを関連付けておきます。

|項目|設定1|設定2|
|:--|:--|:--|
|VPC|クライアントVPNエンドポイントで指定したVPC|クライアントVPNエンドポイントで指定したVPC|
|関連付けるサブネットを選択|10.1.0.0/24|10.1.1.0/24|

### 承認ルールの追加
VPN接続を行ったアクセスを許可する送信先ネットワークを指定します。

今回は既存ですでに作成しているプライベートサブネット２つを追加しておきます。

|項目|設定1|設定2|
|:--|:--|:--|
|アクセスを有効にする送信先ネットワーク|10.1.10.0/24|10.1.11.0/24|
|アクセス権を以下に付与する|アクセス権をすべてのユーザーに許可する|アクセス権をすべてのユーザーに許可する|

## VPNクライアントのセットアップ
上記までの手順で、AWS側の設定は完了したので、VPN接続を行うクライアント側の設定を行っていきます。

`AWS Client VPN`は`OpenVPN`ベースとなるため、`OpenVPN`のクライアントソフトを使用しても接続できるようになっておりますが、`IAM Identity Center`とSAML認証を行う場合はAWS公式のVPNクライアントソフトでなければ接続することはできません。

セルフサービスポータルを有効にしていない場合は以下よりAWS公式VPNクライアントソフトをダウンロードしてインストールします。

　- [AWS Client VPN download](https://aws.amazon.com/jp/vpn/client-vpn-download/)

セルフサービスポータルを有効にしている場合はクライアントVPNエンドポイントの「**詳細**」に表示されている「**セルフサービスポータル URL**」にアクセスすることで以下のようなポータル画面が開くので、VPNクライアントソフトと、設定用のクライアント構成ファイルをダウンロードしてインストールを行います。

ポータル画面アクセス時にはユーザ名等聞かれるため、`IAM Identity Center`に登録されているユーザ名、パスワード、MFA認証の入力を行ってください。

![Monosnap_20230318_101445.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/9a45d670-00eb-2b49-e2b3-1000037f4a43.png)

VPNクライアントを起動すると、以下のようにプロファイル作成方法が表示されるため、ダウンロードしたクライアント構成ファイルを読み込ませてください。

![Monosnap_20230318_102024.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/deabf231-60f1-7259-24cb-623673d268c6.png)

## VPN接続
実際にVPNクライアントを使って接続してみます。

クライアント構成ファイルを読み込んだクライアントVPNの「**接続**」で接続を行うと、`IAM Identity Center`の認証画面が開くため、ユーザ名、パスワード、MFA認証を行いログインします。

![Monosnap_20230318_111748.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/f433a7fa-09f3-abd4-568d-4d4987d67b56.png)

ログイン後、以下のような画面が表示され、VPNクライアントのステータスが「**接続済み。**」となれば接続完了です。

![Monosnap_20230318_115557.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/3b7866f4-17eb-616a-3985-9be83a5ba2e8.png)

接続後、`ifconfig`等で割り振られているIPアドレスを確認すると、クライアントVPNエンドポイントの設定を行った際に指定したアドレス範囲のIPアドレスが割り振られていることが確認できるかと思います。

```bash:VPN接続時に割り振られたアドレスの確認
> ifconfig
（略）
utun3: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1500
	inet 100.64.1.34 --> 100.64.1.34 netmask 0xffffffe0
```

## Pingの実施
VPN接続後、プライベートサブネットに存在するEC2インスタンスにアクセスできるか、`Ping`コマンドで確認してみます。

`Ping`での確認のため、送信先となるEC2インスタンスのセキュリティグループで`ICMP`を許可しておきましょう。

```bash:10.1.10.0/24のEC2インスタンスへのPint
> ping 10.1.10.201
PING 10.1.10.201 (10.1.10.201): 56 data bytes
64 bytes from 10.1.10.201: icmp_seq=0 ttl=126 time=14.467 ms
64 bytes from 10.1.10.201: icmp_seq=1 ttl=126 time=14.333 ms
64 bytes from 10.1.10.201: icmp_seq=2 ttl=126 time=11.598 ms
^C
--- 10.1.10.201 ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 11.598/13.466/14.467/1.322 ms
```

```bash:10.1.11.0/24のEC2インスタンスへのPint
> ping 10.1.11.147
PING 10.1.11.147 (10.1.11.147): 56 data bytes
64 bytes from 10.1.11.147: icmp_seq=0 ttl=126 time=9.901 ms
64 bytes from 10.1.11.147: icmp_seq=1 ttl=126 time=9.102 ms
64 bytes from 10.1.11.147: icmp_seq=2 ttl=126 time=9.930 ms
^C
--- 10.1.11.147 ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 9.102/9.644/9.930/0.384 ms
```

上記の通りプライベートサブネットに存在するEC2インスタンスに対して`Ping`での応答があることが確認できました。

また、今回は、クライアントVPNエンドポイントの設定を行う際、「**スプリットトンネルを有効化**」の設定を有効にしているので、承認ルールで指定した通信以外はVPNトンネルを通りません。

もし、すべての通信をVPNトンネル経由としたい場合は、スプリットトンネルを有効化しないでください。

# Self Service Portal URLのアプリケーションへの紐付け
`AWS Client VPN`のアプリケーションは`IAM Identity Center`とAWS側に作成したIDプロバイダとのSAML認証を通すためのものなので、`AWS Client VPN`のアプリケーションもセルフサービスポータル用のアプリケーションもデフォルトでは選択しても何も表示されません。

何も表示されないのも味気なく、知らない人が見たらエラーと勘違いし、余計な問い合わせが来てしまうかもしれないので、おまけとして`IAM Identity Center`のポータル画面に表示されるアプリケーションのアイコンから`AWS Client VPN`のセルフサービスポータル画面へアクセスできるようにしようと思います。

別に何も表示されなくても気にしないという方は以下の設定は行わなくても問題ありません。

## AWS Client VPN＆セルフサービスポータル用アプリケーションの編集
`IAM Identity Center`の「**Applications**」→Client VPN接続用設定、およびセルフサービスポータル用設定を選択→右上の「**Actions**」から「**Edit configuration**」を選択。

先程空欄としていた「**アプリケーションのプロパティ**」欄の「**Application start URL**」にセルフサービスポータルのURLを入力して設定を反映させます。

URLはClient VPN接続用もセルフサービスポータル用もどちらも同じURLを設定すればOKです。

## セルフサービスポータル画面へのアクセス
`IAM Identity Center`のポータル画面に表示されているClient VPN接続用、セルフサービスポータル用のアイコンを選択して、セルフサービスポータル画面が表示されれば完了です。


# おわりに
今回は`AWS Client VPN`の証明書と認証をそれぞれAWSのマネージドサービスを利用することにより、証明書の管理や認証の一元管理を行うことができました。

`IAM Identity Center`を使わない相互認証方式でのやり方と比べると、以下の作業や管理が不要となるため、運用者の負担は激減するのではないかと思います。

- サーバ・クライアント証明書作成マシンの準備
- サーバ証明書作成
- クライアント証明書作成
- VPN接続ユーザにクライアント証明書を送信
- VPN接続ユーザにクライアント構成ファイルを送信

`IAM Identity Center`はSAML認証が行えることから、今回のVPN接続以外にも色々なサービスと連携することができるので、他のサービスとも連携してみてはいかがでしょうか。