Cloudflareの使用IPレンジのプレフィックスリストを定期的に更新する処理を導入する。

# はじめに
とある案件で、`Cloudflare`が保持するIPレンジを自動で取得する機能があればなぁと思い、`Cloudflare`の使用IPレンジを更新する処理を作ったので紹介したいと思います。

# 機能を導入したきっかけ
先日始めてCDNサービスの`Cloudflare`を使う機会がありました。

同じCDNサービスの1つであるAWSの`CloudFront`は仕事でも使用しており、その際、オリジンサーバへ直接アクセスさせないようにするため、`CloudFront`からオリジンサーバへアクセスするときに使用するIPアドレスが登録されているマネージドプレフィックスリストをセキュリティグループと一緒に使用して、オリジンサーバへのアクセスは`CloudFront`からのアクセスに限定するようなことを行っておりました。

`CloudFront`であれば、VPC設定の「**マネージドプレフィックスリスト**」に`CloudFront`が使用するIPレンジの一覧が登録されているため、簡単にセキュリティグループ設定で送信元IPリストとして使用することができますが、`Cloudflare`はAWSサービスではないので登録されておりません。

幸い、`Cloudflare`が使用するIPレンジは以下で公開されており、APIも存在するということで、じゃあ定期的に公開サイトから一覧を取得して登録してしまおうと思ったのがきっかけです。

- [Cloudflareの使用IPレンジ公開サイト](https://www.cloudflare.com/ja-jp/ips/)

# マネージドプレフィックスリストとは
AWSのVPC設定の中にある「**マネージドプレフィックスリスト**」は複数IPアドレスをまとめたリストで、セキュリティグループ等を作成する際に送信元・送信先IPアドレスとしてまとめて指定するようなことができる便利な機能です。

また、`CloudFront`の使用IPや`Route53`のヘルスチェック時のIPなど、AWSのサービスが使用するIPはあらかじめ登録されているため、登録済みのマネージドプレフィックスリストを指定するだけで、各サービスからのアクセスに限定するようなことができます。

あらかじめ登録されているリスト以外でも自分で新たなリストを登録することもできるので、今回は`Cloudflare`用のマネージドプレフィックスリストを作成しようと思います。

# マネージドプレフィックスリスト定期更新処理
以下より実際に`Cloudflare`の使用IPを登録したマネージドプレフィックスリストを更新する処理を作成していきたいと思います。

今回導入する機能の概要は以下となります。

![CloudflareIPリスト更新処理.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/150cf7d2-6166-b0e3-1361-f5c59d218aa2.png)

処理の内容としては`EventBridge Scheduler`で定期的に`CodeBuild`を実行し、`CodeBuild`で`Cloudflare`の使用IPレンジ公開サイトと、あらかじめ登録済みのマネージドプレフィックスリストのアドレスを比較して、IPアドレスが追加・削除されていればマネージドプレフィックスリストを更新するといったものとなります。

今回は`CodeBuild`で処理を実行していますが、`Lambda`が書けるなら`Lambda`でも問題ありません。

以下より実際に各種サービスを作成していきます。

## マネージドプレフィックスリストの作成
`Cloudflare`のIPアドレスを格納するマネージドプレフィックスリストをあらかじめ作成しておきます。

VPCダッシュボードより「**マネージドプレフィックスリスト**」の「**プレフィックスリストの作成**」から作成していきます。

IPv4用、IPv6用それぞれ作成しようと思うので、以下のように設定しました。

|項目|IPv4プレフィックスリスト用設定|IPv6プレフィックスリスト用設定|
|:--|:--|:--|
|プレフィックスリスト名|cloudflare.global.ipv4.ips|cloudflare.global.ipv6.ips|
|最大エントリ|20|10|
|アドレスファミリー|IPv4|IPv6|
|プレフィックスリストのエントリ|未設定|未設定|
|タグ|※今回は無し|※今回は無し|

プレフィックスリスト名は特に指定があるわけではないので任意の名前で問題ありませんが、最大エントリには注意する必要があります。

マネージドプレフィックスリストは作成時、あらかじめ「**最大エントリ**」で記載されている値の分の領域を確保する必要がありますが、あまりに大きい値を最初から確保してしまうと、セキュリティグループで使用する際にセキュリティグループのデフォルトのルール上限の60に引っかかってしまいます。
※見かけ上IPをまとめているだけで実際には1エントリずつ登録しているのと変わらないため

- [Amazon VPC クォータ - セキュリティグループ](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/amazon-vpc-limits.html)

「**最大エントリ**」で設定している上限に達した場合、拡張はできますが、縮小はできず、拡張する場合も自動で拡張されるわけではなく、オペレーションを行う必要があるので、ギリギリの値に設定すると、アドレスの追加があった場合、エラーとなってしまいます。

2024年6月現在、`Cloudflare`のIPv4アドレス使用レンジ数が15アドレスレンジ、IPv6アドレス使用レンジ数が7アドレスレンジのため、多少余裕を持たせてIPv4の最大エントリを20、IPv6の最大エントリを10としました。

また、プレフィックスリストのエントリですが、後ほど`CodeBuild`でまとめて登録するため、何も登録しなくてOKです。

## CodeBuildの設定
更新処理を行う`CodeBuild`を作成していきます。

- [CodeBuild用IAMポリシーの作成](#codebuild用iamポリシーの作成)
- [CodeBuild用IAMロールの作成](#codebuild用iamロールの作成)
- [CodeBuildの作成](#codebuildの作成)
- [CodeBuildのテスト](#codebuildのテスト)

### CodeBuild用IAMポリシーの作成
後ほど`CodeBuild`に割り当てる必要があるため、あらかじめIAMポリシーとIAMロールを作成しておきます。

IAMダッシュボードの「**ポリシー**」→「**ポリシーの作成**」から、ポリシーエディタより以下のJSONポリシーを流し込みます。

今回はリソースを「**＊**」としてしまっているので、実際にシステムに導入するような場合はリソース指定するなど適宜調整してください。

```json:CodeBuild用IAMポリシー
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "CodeBuildPolicy",
      "Effect": "Allow",
      "Action": [
        "codebuild:CreateReportGroup",
        "codebuild:CreateReport",
        "codebuild:UpdateReport",
        "codebuild:BatchPutCodeCoverages",
        "codebuild:BatchPutTestCases"
      ],
      "Resource": ["*"]
    },
    {
      "Sid": "ManagedPrefixListPolicy",
      "Effect": "Allow",
      "Action": [
        "ec2:GetManagedPrefixListEntries",
        "ec2:ModifyManagedPrefixList",
        "ec2:DescribeManagedPrefixLists"
      ],
      "Resource": ["*"]
    },
    {
      "Sid": "CloudWatchLogsPolicy",
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": ["*"]
    }
  ]
}
```

今回はポリシー名を「**cloudflare-update-ip-codebuild-policy**」として進めます。

### CodeBuild用IAMロールの作成
作成したIAMポリシーを使い、IAMロールも作成します。

「**ロール**」→「**ロールを作成**」から、以下のように設定していき、CodeBuild用IAMロールを作成します。

|項目|設定|
|:--|:--|
|信頼されたエンティティタイプ|AWSのサービス|
|サービスまたはユースケース|CodeBuild|
|ユースケース|CodeBuild|
|許可ポリシー|cloudflare-update-ip-codebuild-policy|
|許可の境界を設定|許可の境界なしでロールを作成|
|ロール名|cloudflare-update-ip-codebuild-role|
|説明|※デフォルトのまま|
|タグ|※今回は無し|

### CodeBuildの作成
CodeBuildダッシュボードの「**ビルドプロジェクト**」→「**プロジェクトを作成する**」よりCodeBuildを作成していきます。

|項目|設定|
|:--|:--|
|プロジェクト名|cloudflare-update-ip-codebuild-proj|
|追加設定|※デフォルトのまま|
|ソースプロバイダ|指定なし|
|プロビジョニングモデル|オンデマンド|
|環境イメージ|マネージド型イメージ|
|コンピューティング|EC2|
|オペレーティングシステム|Amazon Linux|
|ランタイム|Standard|
|イメージ|aws/codebuild/amazonlinux2-x86_64-standard:5.0|
|イメージのバージョン|このランタイムバージョンには常に最新のイメージを使用してください|
|GPU強化コンピューティングを使用|チェック無し|
|サービスロール|既存のサービスロール|
|ロールのARN|※先ほど作成したCodeBuild用IAMロールのARNを指定|
|AWS CodeBuildにこのサービスロールの編集を許可し、このビルドプロジェクトでの使用を可能にする|チェック|
|追加設定|※環境変数のみ指定（環境変数は次表に記載）|
|Buildspec|ビルドコマンドの挿入<br>※Buildspecは後述|
|バッチ設定を定義|チェック無し|
|アーティファクト１タイプ|アーティファクトなし|
|追加設定|※デフォルトのまま|
|CloudWatch Logs|チェック|
|グループ名|/codebuild/cloudflare-update-ip-logs|
|ストリーム名のプレフィックス|cloudflare-update-ip-stream|
|S3ログ|チェックなし|

上記の追加設定で行う環境変数では以下IPv4用、IPv6用の変数を追加し、値には先ほど作成したマネージドプレフィックスリストID（`pl-xxx`で始まるプレフィックスID）を入力します。

|名前|値|タイプ|
|:--|:--|:--|
|PREFIX_LIST_ID_IPV4|pl-xxxxxxxxxxxxxxxxx|プレーンテキスト|
|PREFIX_LIST_ID_IPV6|pl-yyyyyyyyyyyyyyyyy|プレーンテキスト|

`Buildspec`については以下を貼り付けます。

```yml:Buildspec
version: 0.2

env:
  variables:
    # AWS_DEFAULT_REGION      : デフォルトリージョン
    # OLD_LIST_FILE_IPv4_FILE : 古いIPv4アドレスリストファイル名
    # NEW_LIST_FILE_IPv4_FILE : 新しいIPv4アドレスリストファイル名
    # DELETE_LIST_IPv4_FILE   : 削除IPv4アドレスリストファイル名
    # ADD_LIST_IPv4_FILE      : 追加IPv4アドレスリストファイル名
    # OLD_LIST_FILE_IPv6_FILE : 古いIPv6アドレスリストファイル名
    # NEW_LIST_FILE_IPv6_FILE : 新しいIPv6アドレスリストファイル名
    # DELETE_LIST_IPv6_FILE   : 削除IPv6アドレスリストファイル名
    # ADD_LIST_IPv6_FILE      : 追加IPv6アドレスリストファイル名
    # PREFIX_LIST_ID_IPV4     : IPv4マネージドプレフィックスリストID
    # PREFIX_LIST_ID_IPV6     : IPv6マネージドプレフィックスリストID
    AWS_DEFAULT_REGION: "ap-northeast-1"
    OLD_LIST_IPV4_FILE: "list_ipv4_old"
    NEW_LIST_IPV4_FILE: "list_ipv4_new"
    DELETE_LIST_IPV4_FILE: "delete_ipv4_list"
    ADD_LIST_IPV4_FILE: "add_ipv4_list"
    OLD_LIST_IPV6_FILE: "list_ipv6_old"
    NEW_LIST_IPV6_FILE: "list_ipv6_new"
    DELETE_LIST_IPV6_FILE: "delete_ipv6_list"
    ADD_LIST_IPV6_FILE: "add_ipv6_list"
    # PREFIX_LIST_IDは外部変数で指定するためコメントアウト
    # PREFIX_LIST_ID_IPV4: "pl-xxxxxxxxxxxxxxxxx"
    # PREFIX_LIST_ID_IPV6: "pl-yyyyyyyyyyyyyyyyy"

phases:
  pre_build:
    on-failure: ABORT
    commands:
      # IPv4マネージドプレフィックスリストのエントリを取得
      # buildspec.yml内ではステップをまたぐと終了コードで判定できないため、エラーチェック用変数で判定
      - |
        aws ec2 get-managed-prefix-list-entries --prefix-list-id ${PREFIX_LIST_ID_IPV4} | jq -r '.Entries[].Cidr' | sort > ${OLD_LIST_IPV4_FILE}
        ERRCHK_IPV4=${PIPESTATUS[0]}
      # エラー処理
      - |
        if [ ${ERRCHK_IPV4} -ne 0 ]; then
          exit 1
        fi
      # IPv6マネージドプレフィックスリストのエントリを取得
      # buildspec.yml内ではステップをまたぐと終了コードで判定できないため、エラーチェック用変数で判定
      - |
        aws ec2 get-managed-prefix-list-entries --prefix-list-id ${PREFIX_LIST_ID_IPV6} | jq -r '.Entries[].Cidr' | sort > ${OLD_LIST_IPV6_FILE}
        ERRCHK_IPV6=${PIPESTATUS[0]}
      # エラー処理
      - |
        if [ ${ERRCHK_IPV6} -ne 0 ]; then
          exit 1
        fi
      # CloudflareのIPv4IPアドレスリストを取得
      - |
        curl -s --request GET --url https://api.cloudflare.com/client/v4/ips --header 'Content-Type: application/json' | jq -r '.result.ipv4_cidrs[]' | sort > ${NEW_LIST_IPV4_FILE}
        ERRCHK_IPV4=${PIPESTATUS[1]}
      # エラー処理
      - |
        if [ ${ERRCHK_IPV4} -ne 0 ]; then
          exit 1
        fi
      # CloudflareのIPv6IPアドレスリストを取得
      - |
        curl -s --request GET --url https://api.cloudflare.com/client/v4/ips --header 'Content-Type: application/json' | jq -r '.result.ipv6_cidrs[]' | sort > ${NEW_LIST_IPV6_FILE}
        ERRCHK_IPV6=${PIPESTATUS[1]}
      # エラー処理
      - |
        if [ ${ERRCHK_IPV6} -ne 0 ]; then
          exit 1
        fi
      # 比較用ファイル作成
      - diff ${OLD_LIST_IPV4_FILE} ${NEW_LIST_IPV4_FILE} | awk '/^</ {print $2}' > ${DELETE_LIST_IPV4_FILE}
      - diff ${OLD_LIST_IPV4_FILE} ${NEW_LIST_IPV4_FILE} | awk '/^>/ {print $2}' > ${ADD_LIST_IPV4_FILE}
      - diff ${OLD_LIST_IPV6_FILE} ${NEW_LIST_IPV6_FILE} | awk '/^</ {print $2}' > ${DELETE_LIST_IPV6_FILE}
      - diff ${OLD_LIST_IPV6_FILE} ${NEW_LIST_IPV6_FILE} | awk '/^>/ {print $2}' > ${ADD_LIST_IPV6_FILE}
  build:
    on-failure: ABORT
    commands:
      # IPv4マネージドプレフィックスリストの更新判定
      - |
        if [ ! -s ${DELETE_LIST_IPV4_FILE} ] && [ ! -s ${ADD_LIST_IPV4_FILE} ]; then
          # 何も実行しない
          :
        else
          # マネージドプレフィックスリストの現在のバージョン取得と削除＆追加用コマンド作成
          LIST_VERSION_IPV4=$(aws ec2 describe-managed-prefix-lists --prefix-list-ids ${PREFIX_LIST_ID_IPV4} | jq -r '.PrefixLists[].Version')
          DELETE_LIST_IPV4_COMMAND="$(awk '{printf "Cidr=%s ", $1}' ${DELETE_LIST_IPV4_FILE})"
          ADD_LIST_IPV4_COMMAND="$(awk -v timestamp="$(date +'%Y-%m-%d')" '{printf "Cidr=%s,Description=Add_" timestamp "_Cloudflare ", $1}' ${ADD_LIST_IPV4_FILE})"
          # マネージドプレフィックスリストへの追加＆削除がある場合
          if [ -s ${DELETE_LIST_IPV4_FILE} ] && [ -s ${ADD_LIST_IPV4_FILE} ]; then
            aws ec2 modify-managed-prefix-list \
              --prefix-list-id ${PREFIX_LIST_ID_IPV4} \
              --remove-entries ${DELETE_LIST_IPV4_COMMAND} \
              --add-entries ${ADD_LIST_IPV4_COMMAND} \
              --current-version ${LIST_VERSION_IPV4} 2>&1 > /dev/null
            ERRCHK_IPV4=$(echo $?)
          # マネージドプレフィックスリストへの削除がある場合
          elif [ -s ${DELETE_LIST_IPV4_FILE} ] && [ ! -s ${ADD_LIST_IPV4_FILE} ]; then
            aws ec2 modify-managed-prefix-list \
              --prefix-list-id ${PREFIX_LIST_ID_IPV4} \
              --remove-entries ${DELETE_LIST_IPV4_COMMAND} \
              --current-version ${LIST_VERSION_IPV4} 2>&1 > /dev/null
            ERRCHK_IPV4=$(echo $?)
          # マネージドプレフィックスリストへの追加がある場合
          else
            aws ec2 modify-managed-prefix-list \
              --prefix-list-id ${PREFIX_LIST_ID_IPV4} \
              --add-entries ${ADD_LIST_IPV4_COMMAND} \
              --current-version ${LIST_VERSION_IPV4} 2>&1 > /dev/null
            ERRCHK_IPV4=$(echo $?)
          fi
        fi
      # IPv6マネージドプレフィックスリストの更新判定
      - |
        if [ ! -s ${DELETE_LIST_IPV6_FILE} ] && [ ! -s ${ADD_LIST_IPV6_FILE} ]; then
          # 何も実行しない
          :
        else
          # マネージドプレフィックスリストの現在のバージョン取得と削除＆追加用コマンド作成
          LIST_VERSION_IPV6=$(aws ec2 describe-managed-prefix-lists --prefix-list-ids ${PREFIX_LIST_ID_IPV6} | jq -r '.PrefixLists[].Version')
          DELETE_LIST_IPV6_COMMAND="$(awk '{printf "Cidr=%s ", $1}' ${DELETE_LIST_IPV6_FILE})"
          ADD_LIST_IPV6_COMMAND="$(awk -v timestamp="$(date +'%Y-%m-%d')" '{printf "Cidr=%s,Description=Add_" timestamp "_Cloudflare ", $1}' ${ADD_LIST_IPV6_FILE})"
          # マネージドプレフィックスリストへの追加＆削除がある場合
          if [ -s ${DELETE_LIST_IPV6_FILE} ] && [ -s ${ADD_LIST_IPV6_FILE} ]; then
            aws ec2 modify-managed-prefix-list \
              --prefix-list-id ${PREFIX_LIST_ID_IPV6} \
              --remove-entries ${DELETE_LIST_IPV6_COMMAND} \
              --add-entries ${ADD_LIST_IPV6_COMMAND} \
              --current-version ${LIST_VERSION_IPV6} 2>&1 > /dev/null
            ERRCHK_IPV6=$(echo $?)
          # マネージドプレフィックスリストへの削除がある場合
          elif [ -s ${DELETE_LIST_IPV6_FILE} ] && [ ! -s ${ADD_LIST_IPV6_FILE} ]; then
            aws ec2 modify-managed-prefix-list \
              --prefix-list-id ${PREFIX_LIST_ID_IPV6} \
              --remove-entries ${DELETE_LIST_IPV6_COMMAND} \
              --current-version ${LIST_VERSION_IPV6} 2>&1 > /dev/null
            ERRCHK_IPV6=$(echo $?)
          # マネージドプレフィックスリストへの追加がある場合
          else
            aws ec2 modify-managed-prefix-list \
              --prefix-list-id ${PREFIX_LIST_ID_IPV6} \
              --add-entries ${ADD_LIST_IPV6_COMMAND} \
              --current-version ${LIST_VERSION_IPV6} 2>&1 > /dev/null
            ERRCHK_IPV6=$(echo $?)
          fi
        fi
      # エラー処理
      - |
        if [ ${ERRCHK_IPV4} -ne 0 ] || [ ${ERRCHK_IPV6} -ne 0 ]; then
          exit 1
        fi
  post_build:
    on-failure: CONTINUE
    commands:
      # 作業用ファイル削除
      - rm -f ${OLD_LIST_IPV4_FILE} ${NEW_LIST_IPV4_FILE} ${DELETE_LIST_IPV4_FILE} ${ADD_LIST_IPV4_FILE}
      - rm -f ${OLD_LIST_IPV6_FILE} ${NEW_LIST_IPV6_FILE} ${DELETE_LIST_IPV6_FILE} ${ADD_LIST_IPV6_FILE}
```

### CodeBuildのテスト
`CodeBuild`が完成したので、一度実行して動作するかを確認しておきます。

CodeBuildダッシュボードの「**ビルドプロジェクト**」から作成した`CodeBuild`のビルドプロジェクトを選択し、「**ビルドを開始**」で実行してみます。

問題なければ先程何もエントリの登録をしなかったIPv4とIPv6のプレフィックスリストに以下のように`Cloudflare`のIPリストが追加されているはずです。

`CodeBuild`で追加されたエントリについては説明欄に追加した日付が出るようにしているため、説明欄を見て`CodeBuild`で追加されたものなのか確認してもOKです。

![Monosnap_20240602_103306.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/4b17b0d6-4aae-84e2-04b8-be3412129ede.png)

## EventBridge Schedulerの設定
ここまでの設定で一通りの処理はできるようになりましたが、先程作成した`CodeBuild`を定期実行するため、`EventBridge Scheduler`で実行するようにします。

- [EventBridge Scheduler用IAMポリシーの作成](#eventbridge-scheduler用iamポリシーの作成)
- [EventBridge Scheduler用IAMロールの作成](#eventbridge-scheduler用iamロールの作成)
- [EventBridge Schedulerの作成](#eventbridge-schedulerの作成)
- [EventBridge Schedulerのテスト](#eventbridge-schedulerのテスト)

### EventBridge Scheduler用IAMポリシーの作成
先程の`CodeBuild`のIAMポリシーと同じように作成します。

ポリシー名は「**cloudflare-update-ip-eb-policy**」として進めます。

```json:EventBridge Scheduler用IAMポリシー
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "EventBridgeSchedulerPolicy",
      "Effect": "Allow",
      "Action": "codebuild:StartBuild",
      "Resource": "*"
    }
  ]
}
```

### EventBridge Scheduler用IAMロールの作成
IAMロールも同様に作成します。

ただし、`EventBridge Scheduler`はユースケースに登録されていないようなので、「**カスタム信頼ポリシー**」から作成していきます。

|項目|設定|
|:--|:--|
|信頼されたエンティティタイプ|カスタム信頼ポリシー|
|サービスまたはユースケース|CodeBuild|
|ユースケース|CodeBuild|
|許可ポリシー|cloudflare-update-ip-eb-policy|
|許可の境界を設定|許可の境界なしでロールを作成|
|ロール名|cloudflare-update-ip-eb-role|
|説明|※デフォルトのまま|
|タグ|※今回は無し|

カスタム信頼ポリシーは以下で指定します。

```json:EventBridge Schedulerカスタム信頼ポリシー
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Sid": "EventBridgeSchedulerAssumeRole",
			"Effect": "Allow",
			"Principal": {
				"Service": "scheduler.amazonaws.com"
			},
			"Action": "sts:AssumeRole"
		}
	]
}
```

### EventBridge Schedulerの作成
EventBridgeダッシュボードの「**Scheduler**」→「**スケジュール**」の「**スケジュールを作成**」から作成します。

cron式で指定している時間はお好きな時間に指定してください。

|項目|設定|
|:--|:--|
|スケジュール名|cloudflare-update-ip-schedule|
|説明|※今回は無し|
|スケジュールグループ|default|
|頻度|定期的なスケジュール|
|タイムゾーン|(UTC+09:00) Asia/Tokyo|
|スケジュールの種類|cronベースのスケジュール|
|cron式|cron(0 1 * * ? *)|
|フレックスタイムウィンドウ|オフ|
|時間枠|※サマータイム設定は行わないためスキップ|
|ターゲットAPI|テンプレート化されたターゲット|
|選択ターゲット|CodeBuild StartBuild|
|CodeBuildプロジェクト|※先ほど作成したCodeBuildプロジェクトを指定|
|リクエストパラメータ|{}|
|スケジュールを有効化|有効化|
|スケジュール完了後のアクション|NONE|
|再試行ポリシー|再試行|
|イベントの最大経過時間|24hour(s) 0minute(s)|
|再試行回数|185times|
|デッドレターキュー(DLQ)|なし|
|暗号化|チェックなし|
|アクセス許可|※先ほど作成したEventBridge Scheduler用IAMロールを指定|

### EventBridge Schedulerのテスト
先ほど手動で`CodeBuild`を実行して確認しましたが、`EventBridge Scheduler`から実行して動作するかを確認してみます。

cron式で指定した時間に、`EventBridge Scheduler`から`CodeBuild`が実行され、成功していれば完了です。

![Monosnap_20240602_113315.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/6c6a2d34-7e74-5e62-ae2f-e63ac3b2d752.png)

# （おまけ）terraformとシェル
今回の手順をまとめた`terraform`コードをGitHubに置いたので手作業でやりたくない方はお使いください。
※terraform化にあたり、IAMポリシー部分はリソース指定して厳格化しています。

- [GitHub - terraform](https://github.com/sakai00kou/qiita/tree/master/terraform/cloudflare_update_ip)

また、`CodeBuild`でやっていた更新作業をシェルにしました。

- [GitHub - shell](https://github.com/sakai00kou/qiita/blob/master/shell/cloudflare_update_ip.sh)

IPv4、IPv6プレフィックスリストIDをシェル内の`PREFIX_LIST_ID_IPV4`と`PREFIX_LIST_ID_IPV6`に記載し、AWSにアクセス権限がある端末から以下のように実行すれば更新されます。

```bash:シェル実行方法
./cloudflare_update_ip.sh
```

また、更新があれば以下のように結果を確認できます。

```bash:更新があった場合の出力結果例
--------------------
削除リスト
--------------------
# IPv4
192.0.2.0/24
# IPv6
2001:db8::/32

--------------------
追加リスト
--------------------
# IPv4
103.31.4.0/22
104.16.0.0/13
# IPv6
2c0f:f248::/32
```

手軽にシェル実行で更新したい方はこちらをお使いください。

# おわりに
今回は`CodeBuild`で処理を行うようにしましたが、`Lambda`等他の方法でも実装できるので、やりやすい方法で実装してもらえれば良いかなと思います。

なにかのお役に立てれば幸いです。