Amazon VPC Block Public Accessが実現するDefault-Denyな次世代のVPC管理

## はじめに

企業利用において、VPCリソースが作成された瞬間にインターネット公開のリスクがある。というのはやりずらいものがあった。

イメージがわかない人向けに例を挙げると、「インターネットに公開しない」というビジネスルールがあれば、間違って公開リソースを作った時点でルール違反なん？AWS Config Ruleでの修復だと事後解決であって、一旦作れちゃってるよね？みたいなやつです。

この辺の運用を「しっかり」チェックするためにVPCリソースだけCI/CDパイプラインに載せられないね…とかあったんじゃないでしょうか。

本日発表されたAmazon VPC Block Public Accessなら、VPCのIngress/Egressを中央制御できて、エンタープライズ運用に刺さるんじゃないかと注目されているので紹介します。

https://aws.amazon.com/jp/about-aws/whats-new/2024/11/block-public-access-amazon-virtual-private-cloud/

## 機能

一言でいうとS3にあったBlock Public Access(BPA)をVPCにも適応できるようになった。

S3-BPAは大まかにいえば、S3バケットの公開状態やインターネットアクセスの意図しない設定ミスを検出する機能である。詳細はこの辺り。

https://repost.aws/ja/knowledge-center/s3-block-public-access-setting

VPC-BPAはVPCのIngress(受信)とEgress(送信)に着目し、IGW/EIGWやSecurityGroupの設定に関わらずブロックする設定を有効にできる！

中央から全ブロックすると聞くと厳しそうにも見えるが、以下のような柔軟な設定もできる。

- Egress専用の通信許可
    - 例えばVPC内から運用パッチのfetchなどは許容され、Session Managerでは入りやすくなる
- VPC、サブネット単位へのBPAの除外機能
    - これによりVPCの外部アクセスを承認制として運用することができる


## 制約

- 設定はステートフルである
- 除外数はdefault50、緩和可能
- VPC-BPAのスコープにElastic Load BalancingやAWS Global Acceleratorは含まれる
- VPC-BPAのスコープにVPNは含まれない

ステートフルなので、基本的にアカウント-リージョン単位でVPC、サブネットへのIngress/Egressを制御できる、Security Groupの上位スコープ版とイメージすると掴みやすい。

## 検証

実際の操作を通して理解してみる。GUIは誰かが書いてそうなので、AWS CLIを使う。

### 検証環境作成

CDKでこのようにALB＋Fargateな環境を作る。

```ts
import * as cdk from "aws-cdk-lib";
import * as ec2 from "aws-cdk-lib/aws-ec2";
import * as ecs from "aws-cdk-lib/aws-ecs";
import * as ecsPatterns from "aws-cdk-lib/aws-ecs-patterns";
import{ Construct } from "constructs";

export class CdkStack extends cdk.Stack {
	constructor(scope: Construct, id: string, props?: cdk.StackProps) {
		super(scope, id, props);

		const vpc = new ec2.Vpc(this, "Vpc", {
			maxAzs: 2,
			natGateways: 1,
		});

		new ecsPatterns.ApplicationLoadBalancedFargateService(this, "Service", {
			vpc,
			memoryLimitMiB: 512,
			desiredCount: 1,
			cpu: 256,
			taskImageOptions: {
				image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"),
			},
		});
	}
}

```

構築したサンプルアプリへの疎通を確認する。

![スクリーンショット 2024-11-20 141848.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528454/5636a768-61af-263a-4b5a-3b38b7c55b0a.png)


### aws cli v2のupdate

新機能なので従来のバージョンだと動かない。CLIがv2.22.1以上であることを確認する。

```bash
aws --version
aws-cli/2.22.1 Python/3.12.6 Linux/6.1.94-99.176.amzn2023.x86_64 exe/x86_64.amzn.2023
```

試しに今のBPAの状態を見てみる。

```bash
aws ec2 describe-vpc-block-public-access-options --output table
----------------------------------------------------------------------------------------------------
|                                DescribeVpcBlockPublicAccessOptions                               |
+--------------------------------------------------------------------------------------------------+
||                                   VpcBlockPublicAccessOptions                                  ||
|+--------------+-----------------+----------------------------+----------------+-----------------+|
|| AwsAccountId |    AwsRegion    | InternetGatewayBlockMode   |    Reason      |      State      ||
|+--------------+-----------------+----------------------------+----------------+-----------------+|
||  xxxxxxxxxxxx |  ap-northeast-3 |  off                       |  Default State |  default-state  ||
|+--------------+-----------------+----------------------------+----------------+-----------------+|
```

基本的な使い方はAPIのリンクで「vpc-block-public-」あたりでブラウザ検索するのが早い。

https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/index.html

### BPA設定(block-bidirectional)

この辺を参考にCLIで操作し、想定通りSecurityGroupの設定を上書きし、アクセス断ができた。

https://docs.aws.amazon.com/vpc/latest/userguide/security-vpc-bpa.html


```bash
## 無効化
aws ec2  modify-vpc-block-public-access-options --internet-gateway-block-mode block-bidirectional
{
    "VpcBlockPublicAccessOptions": {
        "AwsAccountId": "xxxxxxxxxxxxx",
        "AwsRegion": "ap-northeast-3",
        "State": "update-in-progress",
        "InternetGatewayBlockMode": "block-bidirectional",
        "Reason": "Customer Action",
        "LastUpdateTimestamp": "2024-11-20T05:24:46.879000+00:00"
    }
}

## VPC-BPAの確認
aws ec2 describe-vpc-block-public-access-options --output table
--------------------------------------------------------------------------------------------------------------------------------------------
|                                                    DescribeVpcBlockPublicAccessOptions                                                   |
+------------------------------------------------------------------------------------------------------------------------------------------+
||                                                       VpcBlockPublicAccessOptions                                                      ||
|+--------------+-----------------+---------------------------+------------------------------------+------------------+-------------------+|
|| AwsAccountId |    AwsRegion    | InternetGatewayBlockMode  |        LastUpdateTimestamp         |     Reason       |       State       ||
|+--------------+-----------------+---------------------------+------------------------------------+------------------+-------------------+|
||  xxxxxxxxxxxx |  ap-northeast-3 |  block-bidirectional      |  2024-11-20T05:26:57.428000+00:00  |  Customer Action |  update-complete  ||
|+--------------+-----------------+---------------------------+------------------------------------+------------------+-------------------+|

### 接続確認

curl http://cdksta-servi-zytycjvsaxcc-1257098855.ap-northeast-3.elb.amazonaws.com/ -m 30
curl: (28) Connection timed out after 30001 milliseconds
```

### BPAの除外設定(block-public-access-exclusion)

ちなみに、bidirectionalは双方向(ブロック)を指す単語らしい。

```bash
## BPAから特定VPCの除外
aws ec2 create-vpc-block-public-access-exclusion --internet-gateway-exclusion-mode allow-bidirectional --vpc-id vpc-00b621aaffe2d6c40                                      
{
    "VpcBlockPublicAccessExclusion": {
        "ExclusionId": "vpcbpa-exclude-0f7802868c149558e",
        "InternetGatewayExclusionMode": "allow-bidirectional",
        "ResourceArn": "arn:aws:ec2:ap-northeast-3:xxxxxxxxxxxx:vpc/vpc-00b621aaffe2d6c40",
        "State": "create-in-progress",
        "Reason": "Customer Action",
        "CreationTimestamp": "2024-11-20T06:06:47.013000+00:00",
        "LastUpdateTimestamp": "2024-11-20T06:06:47.013000+00:00"
    }
}

## VPC-BPA Exclusionの確認 (max resultsを書かないと動かない)
aws ec2 describe-vpc-block-public-access-exclusions --max-results 50
{
    "VpcBlockPublicAccessExclusions": [
        {
            "ExclusionId": "vpcbpa-exclude-0f7802868c149558e",
            "InternetGatewayExclusionMode": "allow-bidirectional",
            "ResourceArn": "arn:aws:ec2:ap-northeast-3:xxxxxxxxxxxx:vpc/vpc-00b621aaffe2d6c40",
            "State": "create-complete",
            "Reason": "Customer Action",
            "CreationTimestamp": "2024-11-20T06:06:47.013000+00:00",
            "LastUpdateTimestamp": "2024-11-20T06:09:58.491000+00:00",
            "Tags": []
        },
...

### 接続確認
curl http://cdksta-servi-zytycjvsaxcc-1257098855.ap-northeast-3.elb.amazonaws.com/ -I
HTTP/1.1 200 OK
Date: Wed, 20 Nov 2024 06:13:37 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Server: Apache/2.4.39 () PHP/5.4.16
Upgrade: h2,h2c
X-Powered-By: PHP/5.4.16
```



## ユースケース

### 1. non Internet なエンプラ要件

不要に公開されているVPCを探すのは難しい。　

AWS Config Ruleで確認し、違反した設定を修復する。というのが一般的なプラクティスだが、実装は簡単ではない。

例えばこのルールは「全開放」だけをチェックする。特定のIPレンジだけを公開するのは許容されているが、果たしてそれは正しい公開先なのだろうか？どこかから雑にコピペした誤ったCIDRかもしれない。

https://docs.aws.amazon.com/ja_jp/config/latest/developerguide/vpc-sg-port-restriction-check.html

他にもSG関連のルールがあるが、これは「特定プロトコルのオープンを許可する」もので役違う。

https://docs.aws.amazon.com/ja_jp/config/latest/developerguide/vpc-sg-open-only-to-authorized-ports.html

BPAを使うと、このようにシステム化するには手間なVPCのアクセス設定のレビューを挟みやすくなる。リソース作成に対して、多層防御の外側が一つ増えたイメージだ。


### 2. リソース構築と外部公開の権限分離

VPC群のアクセス設定に外部からゲートをかけるとは、権限を分離できるという意味でもある。

AWSリソース構築用のユーザやロールは最小権限がベストプラクティスだが、それよりは強めに設定してしまっている現場も多いのではないだろうか？

「リソースを作れるからクイックに外部へ公開できる」は開発者の責任が大きくなるのと表裏一体だったが、VPC-BPAで作成と公開の権限を分離できるようになった。

具体的には

- BPAへのアクセスができない開発者
- BPAおよびVPC ReadOnlyしかできない管理者

のように権限を分離できる。チームで「VPCのyamlやtfファイルを目を皿のようにしてレビュー」みたいな運用をマネコンベースに移行できたりもする。

### 3. 未利用リージョンへのガードレール

あー、構築リージョン間違えてたわ！　的なうっかりミスって意外と無くならないのですが、こうして作られたリソースに限って発見がなぜか遅れませんか？(独自の見解)。設定がゆるいVPCだと怖いとこですが、BPAでdefault denyを入れとくことでVPCに関するガードレール相当にできます、ちょっと安心。

一応アクティブなリージョンのデフォルトをdenyにするガードレールscriptを作ったけど……、当然自己責任で頼みます。

```bash
for region in $(aws ec2 describe-regions --query "Regions[?OptInStatus=='opt-in-not-required'].{Name:RegionName}" --output text); do
  aws ec2 modify-vpc-block-public-access-options --internet-gateway-block-mode block-bidirectional --region $region;
done
```

## まとめ

というわけで、Amazon VPC Block Public AccessによってVPCのIngress/Egressを中央制御できるようになりました。既存のビジネスルールにフィットさせるための煩雑な運用が、かなり改善できる現場もあるのではないでしょうか。

余談ですが、触ってて「これってAZ障害を疑似れるかも」という使い道も思いつきました。面白いサービスなので、いろいろナレッジが出てきそうですね。それでは。