全リージョンのデフォルト VPC を削除する Script を AWS CloudShell から実行する

記事タイトルとURLをコピーする

マネージドサービス部 佐竹です。
本日は AWS アカウントにおけるセキュリティリスク軽減のための手法の1つとして、デフォルト VPC の全削除を Script で行う方法について記載してみます。

デフォルト VPC についてのおさらい

AWS アカウントを新規に払い出すと、そのアカウントの全ての利用可能なリージョンには「デフォルト VPC」と呼ばれる VPC が1つ自動的に構築された状態で引き渡されます。

VPC のマネジメントコンソールでは、Default VPC が「Yes」と表示されているものがそれに当たります。VPC が「デフォルト VPC」ではない場合、この表示は「No」となります。

参考 AWS ドキュメント

docs.aws.amazon.com

上記ドキュメントの日本語版より以下引用します。

Amazon VPC の使用開始時には、各 AWS リージョンにデフォルトの VPC があります。デフォルト VPC には、各アベイラビリティーゾーンのパブリックサブネット、インターネットゲートウェイ、および DNS 解決を有効にするための設定があります。そのため、すぐにデフォルト VPC に Amazon EC2 インスタンスの起動を開始できます。デフォルトの VPC では、Elastic Load Balancing、Amazon RDS、および Amazon EMR などのサービスを使用することもできます。

デフォルト VPC は、すぐに使用を開始する場合や、ブログやシンプルなウェブサイトなど、パブリックインスタンスを起動する場合に適しています。デフォルト VPC のコンポーネントは、必要に応じて変更できます。

記載のある通り、デフォルト VPC があることで EC2 インスタンス等の起動/構築までの時間を短縮することも可能です。

ただし便利さとのトレードオフとして、セキュリティリスクを孕みます。

デフォルト VPC のセキュリティリスク

ここからデフォルト VPC が存在していることのセキュリティリスクについて記載します。

デフォルト VPC が存在するということは、AWS アカウントがもし攻撃にさらされた場合に、EC2 インスタンス等のリソースを攻撃者によって容易に構築される危険性がある、という事にもなります。

実際に発生した事例として「IAM ユーザのキーペアが漏洩したことで、海外のリージョンに不正なリソースを大量構築され、AWS のコストが跳ね上がってしまった」という報告を(複数回)耳にしたことがあります。

特に、普段は利用していない「東京リージョン以外のデフォルト VPC」に高コストのリソースを不正に構築されたとしても、なかなか気付きにくいものです。

よって、デフォルト VPC が存在することのセキュリティリスクを鑑み、これらを削除する対応を取る利用者様もいらっしゃいます。もちろん、デフォルト VPC がない状態であったとしても、VPC を新規に作成されてしまえば同様の攻撃を受ける可能性があります。ですが、デフォルト VPC を利用しないのであれば、それを削除しておくことで多少のリスク軽減には役立つはずです。

また、デフォルト VPC はマネジメントコンソールから容易に削除は可能です。しかし、この作業を全てのリージョンで行うのは少々手間がかかりますため、今回は CloudShell から Script で削除を実施した例をご紹介します。

AWS Security Hub への影響

Script の紹介の前に、AWS におけるセキュリティリスクに関連して、AWS Security Hub への影響についても記載します。

実のところデフォルト VPC が存在するだけで、AWS Security Hub への影響があります。

例えば「AWS Foundational Security Best Practices v1.0.0」において、EC2 に関連する以下のコントロールが「Failed」してしまいます。

  • [EC2.2] VPC default security groups should not allow inbound or outbound traffic
  • [EC2.6] VPC flow logging should be enabled in all VPCs
  • [EC2.10] Amazon EC2 should be configured to use VPC endpoints that are created for the Amazon EC2 service
  • [EC2.15] Amazon EC2 subnets should not automatically assign public IP addresses

これらのコントロールが「Failed」し、Security Hub のセキュリティスコアが低下することを防ぐ目的でもデフォルト VPC の削除が推奨されます。

なお上記一覧は現時点での一例です。Security Hub のコントロールは不定期ですが追加や廃止が行われるため、現在把握が可能な範囲で記載しております。

Security Hub controls for Amazon EC2

合わせて以下の公式ドキュメントも参照ください。

docs.aws.amazon.com

合わせて知っておきたい

本題とは逸れますが、セキュリティに関連して「合わせて知っておきたい」ことを記載します。

何故攻撃者は第三者の AWS アカウントに侵入したいのか

何故攻撃者は他人の AWS アカウントに侵入したいのでしょうか?

AWS アカウントには重要な情報は置いていないため、情報が漏洩するリスクはない(よってセキュリティ対策の優先度は下げている)」というように考えている場合は、少し注意が必要かもしれません。

お時間があれば、合わせて以下のブログもご覧ください。

AWS 環境における暗号通貨採掘悪用に備える

blog.serverworks.co.jp

コストの急激な増加を検出するには

先に記載しました高コストのリソースを不正に構築されたような場合、この「急激なコストの増加」を検出することでインシデントを早期に食い止めることが可能です。

これには「AWS Cost Anomaly Detection」と「AWS Budgets」とをそれぞれ利用することで実現が可能です。是非合わせて以下のブログもご覧ください。

AWS Cost Anomaly Detection と AWS Budgets の違いを理解する

blog.serverworks.co.jp

AWS Cost Anomaly Detection で実際に検出された内容を紹介します

blog.serverworks.co.jp

AWS Control Tower Account Factory に関して

AWS Organizations ではなく、AWS Control Tower の Account Factory を利用されている場合はデフォルト VPC がその機能で削除される動作となります。

参考まで、以下のエンジニアブログもご覧ください。

blog.serverworks.co.jp

なお、本件は AWS 公式ドキュメントでも以下の通り記載がされています。

AWS Control Tower と VPC の概要
AWS Control Tower がサポートされている AWS リージョンに新しいアカウントを設定すると、AWS Control Tower は自動的にデフォルトの AWS VPC を削除し、AWS Control Tower によって設定された新しい VPC を設定します。

https://docs.aws.amazon.com/ja_jp/controltower/latest/userguide/vpc-concepts.html

全リージョンのデフォルト VPC を削除する Script

それでは本題です。

前提知識

まずは前提知識として以下の公式ドキュメントをご紹介します。

docs.aws.amazon.com

重要な部分をドキュメントより引用しご紹介します。

If you delete a VPC using the Amazon VPC console, we also delete the following VPC components for you (Amazon VPC コンソールを使用して VPC を削除すると、次の VPC コンポーネントも削除されます) :

・ DHCP options
・ Egress-only internet gateways
・ Gateway endpoints
・ Internet gateways
・ Network ACLs
・ Route tables
・ Security groups
・ Subnets

上記の通りマネジメントコンソールから「デフォルトVPC」を削除する場合は関連するリソースを全て自動的に消してくれるため容易に削除が可能となっています。

ですがこれを Script で行おうとした場合には、デフォルト VPC の削除前に依存関係があるリソースを予め全て削除しておく必要があります。そして先の公式ドキュメントには、AWS CLI においては以下の順で削除(とデタッチ)を行うように記載がされています。

  1. セキュリティグループの削除
  2. ネットワーク ACL の削除
  3. サブネットの削除
  4. ルートテーブルの削除
  5. インターネットゲートウェイのデタッチ
  6. インターネットゲートウェイの削除
  7. Egress-Only インターネットゲートウェイの削除
  8. VPC の削除

ただし、未使用のデフォルトVPC を削除する場合は以下の通りにすることが可能です。

  • セキュリティグループは削除せずとも VPC と同時に自動的に削除される
  • ネットワーク ACL とルートテーブルも削除せずとも VPC と同時に自動的に削除される
  • Egress-Only インターネットゲートウェイはデフォルト VPC には作成されていないため作業不要

よって、以下の処理だけ行えば削除可能となります。

  1. VPC に関連する全てのサブネットの削除
  2. インターネットゲートウェイのデタッチ
  3. インターネットゲートウェイの削除
  4. VPC の削除

ここまでが前提です。

Script (create-aws-cli-shell-delete-all-default-vpc.sh)

以下は今回サンプルとして作成した Script です。

可能であれば、ファイル名は create-aws-cli-shell-delete-all-default-vpc.sh として利用してください*1

#!/bin/bash
 
# ログファイルのパスを指定
log_file="create-aws-cli-shell-delete-all-default-vpc.log"
 
# コマンドをログファイルに追記する関数
function log_command {
    echo "$@" >>"$log_file"
}
 
# デフォルトVPCが存在するかを確認する関数
function check_default_vpc {
    local region=$1
    aws ec2 describe-vpcs --region "$region" --filters "Name=isDefault,Values=true" --query 'Vpcs[0].VpcId' --output text 2>/dev/null
}
 
# 実行可能な.shファイルを出力する関数
function output_sh_file {
    local sh_file="delete-default-vpc.sh"
    echo "#!/bin/bash" >"$sh_file"
    echo >>"$sh_file"
 
    for region in $(aws ec2 describe-regions --query 'Regions[].RegionName' --output text); do
        default_vpc=$(check_default_vpc "$region")
        if [ -n "$default_vpc" ] && [ "$default_vpc" != "None" ]; then
            echo "echo \"Region: $region, Deleting VPC: $default_vpc\"" >>"$sh_file"
 
            # Delete Subnets
            for subnet_id in $(aws ec2 describe-subnets --region "$region" --filters "Name=vpc-id,Values=$default_vpc" --query "Subnets[].SubnetId" --output text); do
                echo "aws ec2 delete-subnet --region $region --subnet-id $subnet_id" >>"$sh_file"
            done
 
            # Detach and Delete Internet Gateway
            igw_id=$(aws ec2 describe-internet-gateways --region "$region" --filters "Name=attachment.vpc-id,Values=$default_vpc" --query "InternetGateways[0].InternetGatewayId" --output text)
            if [ -n "$igw_id" ] && [ "$igw_id" != "None" ]; then
                echo "aws ec2 detach-internet-gateway --region $region --internet-gateway-id $igw_id --vpc-id $default_vpc" >>"$sh_file"
                echo "aws ec2 delete-internet-gateway --region $region --internet-gateway-id $igw_id" >>"$sh_file"
            fi
 
            # Delete the VPC
            echo "aws ec2 delete-vpc --region $region --vpc-id $default_vpc" >>"$sh_file"
            echo >>"$sh_file" # Regionごとに改行する
        else
            echo "echo \"Region: $region, デフォルトVPCが見つかりません。次のリージョンに進みます。\"" >>"$sh_file"
            echo >>"$sh_file"
        fi
    done
}
 
read -p "This script will generate a .sh file to delete the Default VPC and its associated resources in all regions. Do you want to continue? (Yes/No): " confirmation
 
if [ "$confirmation" == "Yes" ]; then
    output_sh_file
    echo "Generated delete-default-vpc.sh file successfully."
    log_command "Generated delete-default-vpc.sh file successfully."
else
    echo "Aborted. No action was taken."
    log_command "Aborted. No action was taken."
fi

なお、この Shell Script は必要があれば適切にカスタマイズ及び修正してご利用して頂いて問題ございません。

Script の仕様等

Script の仕様等について記載します。

  • 実行前に Yes/No を確認し、Yes とタイプしたときのみ Script が実行されます
  • 正常に処理が完了すると、全リージョンの「デフォルト VPC」を削除する Script である delete-default-vpc.sh別途作成されます
  • delete-default-vpc.sh を実行すると、全リージョンの「デフォルト VPC」が順に削除されます
  • 「デフォルト VPC」が存在しないリージョンはスキップされます

よって、本 Script 単体の実行は安全です。何らかのリソースを削除するものではありません。実際のリソース削除は delete-default-vpc.sh を実行することで行います。

delete-default-vpc.sh はシンプルなリソース削除用 AWS CLI がリージョン別に記載されているのみで、「これから何を行なうことになるのか?」を判断しやすく、可読性が高いものとなっています。

また削除コマンドはリージョン別に列挙されているため、実行したくないリージョンにおいてはその記述をまとめて削除することで、特定のリージョンのみを除外することも容易です。

なお、EC2 インスタンスなどのリソースが VPC に存在する場合は Subnet の削除に失敗し、Script が正常に動作しない場合があります。本 Script は AWS アカウントが払い出された直後等のタイミングにおいて、利用がされていないデフォルト VPC をまとめて削除することを目的として記載がされている点に留意ください。

Script の利用方法について

事前準備

ここからは実際に利用しながら説明していきます。

まずは先に掲載しました Script を create-aws-cli-shell-delete-all-default-vpc.sh としてローカルに保存します。

Windows OS の場合、改行コードが不正になる場合があります。エディタの置換機能を用いて、正規表現を利用した \r(CR) の削除をお勧めします。

CloudShell へのアップロード

どのリージョンでも問題ありませんので、AWS CloudShell を起動した後、画面右上の「Action」から「Upload file」で create-aws-cli-shell-delete-all-default-vpc.sh をアップロードします。

create-aws-cli-shell-delete-all-default-vpc.sh の実行

アップロードが完了したら bash create-aws-cli-shell-delete-all-default-vpc.sh で Script を実行します。

そうすると、This script will generate a .sh file to delete the Default VPC and its associated resources in all regions. Do you want to continue? (Yes/No): と確認が出るため「Yes」とタイプ後に Enter を押下してください。

無事に Script が完了すると、delete-default-vpc.sh が作成されます。

作成された delete-default-vpc.sh の確認

念のため、delete-default-vpc.sh を確認します。cat delete-default-vpc.sh 等として、内容を表示します。

今回、2つのリージョン以外は全ての デフォルト VPC を削除済のため、2つのリージョンのみが対象として AWS CLI のコマンドが作成されました。画像の「赤い枠内」が1つのリージョンに対する処理となっています。

もしデフォルト VPC の削除から除外したい対象リージョンがある場合は、この1つのセクションごと削除してください。

そして後はこれを実行するだけですが、その前にデフォルト VPC の存在確認を以下の通り行っておきます。

デフォルト VPC の存在確認(作業前)

delete-default-vpc.sh を実行する前に、以下の Script を CloudShell から実行します。

# リージョンの一覧を取得
regions=$(aws ec2 describe-regions --query 'Regions[].RegionName' --output json | jq -r '.[]')
 
# デフォルトVPCをチェック
for region in $regions; do
    default_vpc=$(aws ec2 describe-vpcs --region $region --filters Name=isDefault,Values=true --query 'Vpcs[0].VpcId' --output text)
    if [ ! -z "$default_vpc" ]; then
        echo "Region: $region, VpcId: $default_vpc"
    fi
done

結果は以下の通りとなり、各リージョンに「デフォルト VPC」の有無が確認できます。None は対象が存在しないことを示しています。

上画像の通り、今回は以下の2つのリージョンの各デフォルト VPC が削除できれば全て削除されたことになります。

  • Region: ap-south-2, VpcId: vpc-06be93093042800b9
  • Region: af-south-1, VpcId: vpc-023eb03ebe7a159df

delete-default-vpc.sh の実行

事前チェックが完了したため bash delete-default-vpc.sh として Script を実行します。

この Script の処理によって AWS CLI によって実際のリソースが削除されます。

Script の実行が完了しました。

デフォルト VPC の存在確認(作業後)

再度、存在確認のための Script を CloudShell から実行します。内容は同様のものですが、念のため再掲します。

# リージョンの一覧を取得
regions=$(aws ec2 describe-regions --query 'Regions[].RegionName' --output json | jq -r '.[]')
 
# デフォルトVPCをチェック
for region in $regions; do
    default_vpc=$(aws ec2 describe-vpcs --region $region --filters Name=isDefault,Values=true --query 'Vpcs[0].VpcId' --output text)
    if [ ! -z "$default_vpc" ]; then
        echo "Region: $region, VpcId: $default_vpc"
    fi
done

結果は以下の通り、全リージョンが None つまりデフォルト VPC がないという結果を返しています。

これでデフォルト VPC の削除作業は完了です。

もしデフォルト VPC が必要になった場合には

現在はマネジメントコンソールの VPC のアクションから「Create default VPC」が可能となっています。

確認画面が表示されますので「Create default VPC」を押下すると、すぐに作成が完了します。

念のため作成後に「デフォルト VPC の存在確認」の Script を再実行してみます。

この通り、デフォルト VPC が復旧していることがわかります。

もしデフォルト VPC が必要なリージョンが出た場合は、本作業でリージョンごとに復旧対応が可能です。

参考までに、AWS CLI では create-default-vpc が利用可能です。

docs.aws.amazon.com

上画像の通り、--region 引数を利用することで、特定リージョンの復旧も容易です。

まとめ

本ブログでは AWS アカウントにおけるセキュリティリスク軽減のための手法の1つである「全リージョンのデフォルト VPC の削除」を AWS CloudShell から Script で行う方法について記載しました。

本文に記載しました通り「デフォルト VPC の削除」は AWS Security Hub のスコア向上にも役立つ対応ですため、エンドユーザ様によってはメンバーアカウントの払い出しのタイミングで都度実施する運用としている場合もあります。

本 Script が何らかの役に立てば幸いです。

では、またお会いしましょう。

*1:ソースコードを色付けして表示する(シンタックスハイライト)機能を利用すると改行が消えてしまうため、見た目上の都合、苦肉の策で半角スペースを入れている箇所があります。お手数ですが気になる方は置換等を行い削除してください

佐竹 陽一 (Yoichi Satake) エンジニアブログの記事一覧はコチラ

マネージドサービス部所属。AWS資格全冠。2010年1月からAWSを利用してきています。2021-2022 AWS Ambassadors/2023-2024 Japan AWS Top Engineers/2020-2024 All Certifications Engineers。AWSのコスト削減、最適化を得意としています。