VPC Latticeの認証ポリシーについて理解を深める

# はじめに
先日（4/11）にAWS主催のApplication Networking Roadshowに参加しました。
その後、VPC Latticeの認証ポリシーについて少し理解を深めたので、共有したいと思います。

# 本記事の対象者
* VPC Latticeの認証ポリシーを使いこなしたい方

# 本記事で書かないこと
* VPC Latticeの基本的な概念
* VPC Latticeそのもののユースケース
⇒これはBlackbeltやその他公式資料を参照してください

https://docs.aws.amazon.com/ja_jp/vpc-lattice/latest/ug/what-is-vpc-lattice.html

https://pages.awscloud.com/rs/112-TZM-766/images/AWS-Black-Belt_2025_AmazonVPCLattice_0122_v1.pdf

* VPC Latticeの通信制御方法の使い分け（そもそも、認証ポリシーを使うか否かの話）
⇒こちらも触れませんが、他の方の記事に詳しく記載されています

https://dev.classmethod.jp/articles/lattice-iam-security-choice/
 
# 認証ポリシーの基本的な仕様
* IAMポリシードキュメントの形式で記載される認証認可です。厳密にはIAM認証ではなくVPC Latticeの独自のものとなります
* VPC Latticeのサービスと、サービスネットワークに1つずつ付与することができます
* IAMと同様、明示的な許可が必要となります
* IAMの許可と、認証ポリシーの許可の両方をもって、通信が許可されます
* リクエスタはAWSクレデンシャル(SigV4署名)付きリクエストを行います

## 認証ポリシーを利用した場合の認証認可の流れ
VPC Latticeのサービスが通信を受け取ると、次のような流れになります。

1\. 関連するIAMポリシーと認証ポリシーを収集します
2\. ポリシーのセットを評価します
* リクエスタのオペレーションを実行する権限（IAMポリシー）を評価
* サービスネットワークの認証ポリシーによって許可されているかを確認する。明示的な許可または、認証タイプが"なし"なら次へ
* サービスの認証ポリシーによって許可されているかを確認する。明示的な許可または、認証タイプが"なし"なら許可する
* 明示的な拒否は明示的な許可に優先（IAMと同じ）

流れを図で記載すると次のようになります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308706/cbf8f4e3-cff7-4b7d-9f10-cbefd1ffcccc.png">

# リクエスタ側に必要なIAMポリシー
リクエスタとなるリソースにVPC Latticeの実行権限が必要になります。
最低限下記のポリシーが必要となります。

```VPCLatticeInvoke
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "vpc-lattice-svcs:Invoke"
            ],
            "Resource": "*",
            "Effect": "Allow"
        }
    ]
}
```

# デフォルトの認証ポリシー
VPC Latticeのサービスまたはサービスネットワークの認証タイプを`AWS_IAM`として、`認証されたアクセスのみ許可`を選択すると、下記のポリシーが付与されます。
```
{
    "Statement": {
        "Effect": "Allow",
        "Principal": "*",
        "Resource": "*",
        "Condition": {
            "StringNotEqualsIgnoreCase": {
                "aws:PrincipalType": "anonymous"
            }
        },
        "Action": "*"
    }
}
```
このポリシーについて解説します。ストレートに読むと、こうなります。
* "anonymous"（匿名ユーザ）以外の場合 、許可する

つまり、AWSクレデンシャル(SigV4署名)付きリクエストを許可し、SigV4署名がない通信を拒否する、ということになります。

# 認証ポリシーで記載可能なこと
認証ポリシーによる認証認可を行う場合、Condition要素に詳細を記載します。
VPC Lattice固有で記載可能なことをまとめると、下記の通りとなります。

|条件キー|内容|例|タイプ|
|---|---|---|---|
|vpc-lattice-svcs:Port|特定のTCPポート番号の指定|80|数値|
|vpc-lattice-svcs:RequestHeader/header-name: value|リクエストヘッダ名と値のペア|content-type: application/json|文字列|
|vpc-lattice-svcs:RequestMethod|リクエストメソッド（GET/POSTなど）|GET|文字列|
|vpc-lattice-svcs:RequestQueryString/key-name: value|クエリ文字列のキーと値のペア|quux: [corge, grault]|文字列|
|vpc-lattice-svcs:ServiceNetworkArn|接続元のVPC Lattice サービスネットワークのARN | arn:aws:vpc-lattice:{AWS_Region}:{AWS_AccountID}:servicenetwork/ {Lattice_Service_Network_ID} |ARN|
|vpc-lattice-svcs:ServiceArn| 接続元のVPC Lattice サービスのARN  | arn:aws:vpc-lattice:{AWS_Region}:{AWS_AccountID}:service/{Lattice_Service_ID}  |ARN|
|vpc-lattice-svcs:SourceVpc| 接続元のVPC ID | vpc-XXXXXXXXXXXX |文字列|
|vpc-lattice-svcs:SourceVpcOwnerAccount| 接続元のVPCの所有者のAWSアカウント | XXXXXXXXXXXX|数字|

その他、`aws:PrincipalOrgID`や`aws:SourceIp`といったIAMで使うグローバル条件キーを使うこともできます。
条件キーは複数指定することもできます。

# 認証ポリシーのベストプラクティス

これらの仕様を踏まえた、認証ポリシーのベストプラクティスを検討します。

### サービスネットワーク側の認証ポリシーのベストプラクティス
ターゲットグループに応じた様々なサービスへの接続を行うため、リクエスタの署名の有無や、特定のIAMロールを保持しているかといった荒い条件で指定します。

### サービス側の認証ポリシーのベストプラクティス
サービス側（受信側）の固有の条件を記載し、きめ細やかな条件に応じた認証ポリシーを設定します。これにより、サービス側で不要なリクエストを受け取らないような制御ができるようになります。

# ケース別の認証ポリシー例
ケースごとの認証ポリシー例を記載します。

## サービスネットワークでの認証ポリシー例
### 特定のIAMロールが付与されたリソースを許可する際の認証ポリシー
```
{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Effect": "Allow",
         "Principal": {
            "AWS": [
               "arn:aws:iam::{AWS_AccountID}:role/{IAM_Role_Name}"
            ]
         },
         "Action": "vpc-lattice-svcs:Invoke",
         "Resource": "*"
         ]
      }
   ]
}
```
## サービスでの認証ポリシー例
### HTTPヘッダに特定のカスタムヘッダを含む場合の認証ポリシー
```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "vpc-lattice-svcs:Invoke",
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "vpc-lattice-svcs:RequestHeader/x-custom-header": "expected-value"
                }
            }
        }
    ]
}
```
### 特定のVPCからの認証されたリクエストのみを許可する場合の認証ポリシー
```
{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Effect": "Allow",
         "Principal": "*",
         "Action": "vpc-lattice-svcs:Invoke",
         "Resource": "*",
         "Condition": {
            "StringNotEquals": {
               "aws:PrincipalType": "Anonymous"
            },
            "StringEquals": {
               "vpc-lattice-svcs:SourceVpc": "{VPC_ID}"
            }
         }
      }
   ]
}
```
### 特定のアカウントIDのVPC所有者のみの接続を許可する場合の認証ポリシー
```
{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Effect": "Allow",
         "Principal": {
            "AWS": "arn:aws:iam::{AWS_ACCOUNT_ID}:root"
         },
         "Action": "vpc-lattice-svcs:Invoke",
         "Resource": "*",
         "Condition": {
            "StringEquals": {
               "vpc-lattice-svcs:SourceVpcOwnerAccount": "{AWS_ACCOUNT_ID}"
            }
         }
      }
   ]
}
```

### 特定のOrganizationsに所属するリソースからのみの接続を許可する場合の認証ポリシー
```
{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Effect": "Allow",
         "Principal": "*",
         "Action": "vpc-lattice-svcs:Invoke",
         "Resource": "*",
         "Condition": {
            "StringEquals": {
               "aws:PrincipalOrgID": [ 
                  "{Organizations_ID}"
               ]
            }
         }
      }
   ]
}
```

# まとめ
VPC Latticeの認証ポリシーは概念的にはIAMと同じもので、独自の条件キーを付加することでネットワークレベルでの細やかな認証認可を盛り込むことができるようになります。
ぜひ認証ポリシーを活用して、柔軟かつセキュアなネットワークの構築を行ってみてください！