Windows 11 で MFA 認証を使ってスイッチロール(AssumeRole)し Terraform を実行する

2024.04.24

コーヒーが好きな emi です。

「別の AWS アカウントにスイッチロールして terraform コマンドを実行したいな、でも providerprofile の設定を書きたくないないな」

と思っていたところ、以下ブログが公開されました。これで解決できそうです。

早速手元の Windows 11 で試してみましたので、コマンドを紹介します。

前提

  • 端末は Windows 11
  • Git for Windows インストール済
  • AWS CLI インストール済
  • Terraform インストール済 *1 *2
  • Visual Studio Code(以降 VSCode と省略)インストール済
  • VSCode に Terraform 拡張導入済
  • VSCode で git コマンド、AWS CLI コマンド、terraform コマンドが利用できる状態になっている
  • VSCode のターミナルは PowerShell

AWS CLI の設定情報

Windows で AWS CLI をデフォルトでインストールした場合、AWS CLI をインストールしたユーザーのホームディレクトリの「.aws」の配下(C:\Users\ユーザー\.aws)に、設定ファイル(config)と認証情報ファイル(credentials)があります。

~/.aws/config

# source AWS account
[default] 
region = ap-northeast-1
output = json

# destination AWS account IAM role : kitani.emi 
[profile kitani.emi]
region = ap-northeast-1
output = json
role_arn = arn:aws:iam::スイッチ先AWSアカウントID:role/kitani.emi
source_profile = default 
mfa_serial = arn:aws:iam::スイッチ元AWSアカウントID:mfa/kitani.emi

# Get credentials for terraform
[profile kitani.emi-tf]
credential_process = aws configure export-credentials --profile kitani.emi # Can be passed in the environment variable AWS_PROFILE instead of stating it on the tf file side.

上記 config ファイルでは 3 つのプロファイルを設定しています。

  • [default] プロファイル
    • 標準の AWS CLI 設定で、特定のプロファイルを指定しない場合に使用される
  • [profile kitani.emi]
    • スイッチ先 AWS アカウントの IAM ロール(kitani.emi)にスイッチするためのプロファイル
  • [profile kitani.emi-tf]
    • credential_process を使用し kitani.emi プロファイルを通じて得られる認証情報を自動的に取得
    • これを利用すると Terraform が AWS リソースにアクセスできる

~/.aws/credentials

# source AWS account
[default]
aws_access_key_id = YOUR_ACCESS_KEY
aws_secret_access_key = YOUR_SECRET_ACCESS_KEY

環境変数の設定

以下のコマンドでスイッチ先 AWS アカウントの IAM ロールのプロファイル [profile kitani.emi] の認証情報を確認します。MFA 認証をしていない場合、途中 MFA の 6 桁のコードの入力を求められます。

aws configure export-credentials --profile kitani.emi

▼実行結果

PS C:\Users\ユーザー\Documents\Terraform\terraform-dynamic-aws-waf-rules\envs\dev-waf> aws configure export-credentials --profile kitani.emi
Enter MFA code for arn:aws:iam::スイッチ元AWSアカウントID:mfa/cm-kitani.emi: # ここで MFA の 6 桁のコードを入力する
{
  "Version": 1,
  "AccessKeyId": "ASXXXXXXXXXXXXXXXXXX",
  "SecretAccessKey": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "SessionToken": "XXXXXXXXXX~~~XXXXXXXXXX",
  "Expiration": "2024-04-23T01:13:07+00:00"
}
PS C:\Users\ユーザー\Documents\Terraform\terraform-dynamic-aws-waf-rules\envs\dev-waf>

export-credentials は指定されたプロファイルの認証情報を JSON 形式で標準出力に出力します。上記のようにコマンドが正常に実行され、認証情報が出力されれば正常にプロファイル設定できています。
この [profile kitani.emi] の認証情報を [profile kitani.emi-tf] として保存し、Terraform 実行時に利用するというわけです。

VSCode のターミナル(PowerShell)で以下コマンドを実行し、環境変数で profile を設定します。

$env:AWS_PROFILE="kitani.emi-tf"

▼実行結果例

PS C:\Users\ユーザー\Documents\Terraform\terraform-dynamic-aws-waf-rules\envs\dev-waf> $env:AWS_PROFILE="kitani.emi-tf"
PS C:\Users\ユーザー\Documents\Terraform\terraform-dynamic-aws-waf-rules\envs\dev-waf>

これにより、現在のセッションで指定したプロファイルが Terraform によって使用されます。

Terraform コマンドの実行

環境変数を設定した後、通常通り Terraform コマンドを実行します。

今回は例として Terraform でパスと IP を指定して AWS WAF のルールグループを動的に生成する | DevelopersIO で使用した以下のコードをローカルに git clone し、S3 バケットや tfstate ファイルの情報を指定して terraform コマンドで展開しました。

環境変数 AWS_PROFILE でプロファイル kitani.emi-tf が設定されているため、Terraform はこのプロファイルを使用して AWS リソースにアクセスしています。

terraform init

実行コマンド

terraform init

▼実行結果

PS C:\Users\ユーザー\Documents\Terraform\terraform-dynamic-aws-waf-rules\envs\dev-waf> terraform init

Initializing the backend...
Enter MFA code for arn:aws:iam::スイッチ元AWSアカウントID:mfa/kitani.emi: 
Initializing modules...

Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Using previously-installed hashicorp/aws v5.46.0

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
PS C:\Users\ユーザー\Documents\Terraform\terraform-dynamic-aws-waf-rules\envs\dev-waf>

terraform plan

長いので結果はトグル内にしまっていますが、terraform コマンドの実行は成功しています。

実行コマンド

terraform plan
実行結果(クリックで展開)
PS C:\Users\ユーザー\Documents\Terraform\terraform-dynamic-aws-waf-rules\envs\dev-waf> terraform plan                    
    
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the    
following symbols:
  + create

Terraform will perform the following actions:

  # module.waf.aws_cloudwatch_log_group.cwlogs will be created
  + resource "aws_cloudwatch_log_group" "cwlogs" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + log_group_class   = (known after apply)
      + name              = "aws-waf-logs-alb-webacl"
      + name_prefix       = (known after apply)
      + retention_in_days = 30
      + skip_destroy      = false
      + tags              = {
          + "Name" = "aws-waf-logs-alb-webacl"
        }
      + tags_all          = {
          + "Name" = "aws-waf-logs-alb-webacl"
        }
    }

  # module.waf.aws_wafv2_ip_set.access_ristrict["access-ristrict-sample2"] will be created
  + resource "aws_wafv2_ip_set" "access_ristrict" {
      + addresses          = [
          + "0.0.0.0/1",
          + "128.0.0.0/1",
        ]
      + arn                = (known after apply)
      + description        = "access-ristrict-sample2-ristrict-ipsets"
      + id                 = (known after apply)
      + ip_address_version = "IPV4"
      + lock_token         = (known after apply)
      + name               = "access-ristrict-sample2-ristrict-ipsets"
      + scope              = "REGIONAL"
      + tags               = {
          + "Name" = "access-ristrict-sample2-ristrict-ipsets"
        }
      + tags_all           = {
          + "Name" = "access-ristrict-sample2-ristrict-ipsets"
        }
    }

  # module.waf.aws_wafv2_ip_set.access_ristrict["access-ristrict-sample3"] will be created
  + resource "aws_wafv2_ip_set" "access_ristrict" {
      + addresses          = [
          + "0.0.0.0/1",
          + "128.0.0.0/1",
        ]
      + arn                = (known after apply)
      + description        = "access-ristrict-sample3-ristrict-ipsets"
      + id                 = (known after apply)
      + ip_address_version = "IPV4"
      + lock_token         = (known after apply)
      + name               = "access-ristrict-sample3-ristrict-ipsets"
      + scope              = "REGIONAL"
      + tags               = {
          + "Name" = "access-ristrict-sample3-ristrict-ipsets"
        }
      + tags_all           = {
          + "Name" = "access-ristrict-sample3-ristrict-ipsets"
        }
    }

  # module.waf.aws_wafv2_rule_group.access_ristrict["access-ristrict-sample2"] will be created
  + resource "aws_wafv2_rule_group" "access_ristrict" {
      + arn         = (known after apply)
      + capacity    = 3
      + description = "access-ristrict-sample2-ristrict-waf-rulegp"
      + id          = (known after apply)
      + lock_token  = (known after apply)
      + name        = "access-ristrict-sample2-ristrict-waf-rulegp"
      + name_prefix = (known after apply)
      + scope       = "REGIONAL"
      + tags_all    = (known after apply)

      + rule {
          + name     = "access-ristrict-sample2-ristrict-rule"
          + priority = 1

          + action {
              + block {
                }
            }

          + statement {
              + and_statement {
                  + statement {
                      + byte_match_statement {
                          + positional_constraint = "STARTS_WITH"
                          + search_string         = "/ristrict/sample2/"

                          + field_to_match {
                              + uri_path {}
                            }

                          + text_transformation {
                              + priority = 0
                              + type     = "NONE"
                            }
                        }
                    }
                  + statement {
                      + not_statement {
                          + statement {
                              + ip_set_reference_statement {
                                  + arn = (known after apply)
                                }
                            }
                        }
                    }
                }
            }

          + visibility_config {
              + cloudwatch_metrics_enabled = true
              + metric_name                = "access-ristrict-sample2-ristrict-rule"
              + sampled_requests_enabled   = true
            }
        }

      + visibility_config {
          + cloudwatch_metrics_enabled = true
          + metric_name                = "access-ristrict-sample2-ristrict-rulegp"
          + sampled_requests_enabled   = true
        }
    }

  # module.waf.aws_wafv2_rule_group.access_ristrict["access-ristrict-sample3"] will be created
  + resource "aws_wafv2_rule_group" "access_ristrict" {
      + arn         = (known after apply)
      + capacity    = 3
      + description = "access-ristrict-sample3-ristrict-waf-rulegp"
      + id          = (known after apply)
      + lock_token  = (known after apply)
      + name        = "access-ristrict-sample3-ristrict-waf-rulegp"
      + name_prefix = (known after apply)
      + scope       = "REGIONAL"
      + tags_all    = (known after apply)

      + rule {
          + name     = "access-ristrict-sample3-ristrict-rule"
          + priority = 1

          + action {
              + block {
                }
            }

          + statement {
              + and_statement {
                  + statement {
                      + byte_match_statement {
                          + positional_constraint = "STARTS_WITH"
                          + search_string         = "/ristrict/sample3/"

                          + field_to_match {
                              + uri_path {}
                            }

                          + text_transformation {
                              + priority = 0
                              + type     = "NONE"
                            }
                        }
                    }
                  + statement {
                      + not_statement {
                          + statement {
                              + ip_set_reference_statement {
                                  + arn = (known after apply)
                                }
                            }
                        }
                    }
                }
            }

          + visibility_config {
              + cloudwatch_metrics_enabled = true
              + metric_name                = "access-ristrict-sample3-ristrict-rule"
              + sampled_requests_enabled   = true
            }
        }

      + visibility_config {
          + cloudwatch_metrics_enabled = true
          + metric_name                = "access-ristrict-sample3-ristrict-rulegp"
          + sampled_requests_enabled   = true
        }
    }

  # module.waf.aws_wafv2_web_acl.web_acl will be created
  + resource "aws_wafv2_web_acl" "web_acl" {
      + application_integration_url = (known after apply)
      + arn                         = (known after apply)
      + capacity                    = (known after apply)
      + description                 = "alb-wabacl"
      + id                          = (known after apply)
      + lock_token                  = (known after apply)
      + name                        = "alb-webacl"
      + scope                       = "REGIONAL"
      + tags                        = {
          + "Name" = "alb-webacl"
        }
      + tags_all                    = {
          + "Name" = "alb-webacl"
        }

      + default_action {
          + allow {
            }
        }

      + rule {
          + name     = "Access-Ristrict-Sample2PathIpRestriction"
          + priority = 1001

          + override_action {
              + none {}
            }

          + statement {
              + rule_group_reference_statement {
                  + arn = (known after apply)
                }
            }

          + visibility_config {
              + cloudwatch_metrics_enabled = true
              + metric_name                = "Access-Ristrict-Sample2PathIpRestriction"
              + sampled_requests_enabled   = true
            }
        }
      + rule {
          + name     = "Access-Ristrict-Sample3PathIpRestriction"
          + priority = 1002

          + override_action {
              + none {}
            }

          + statement {
              + rule_group_reference_statement {
                  + arn = (known after apply)
                }
            }

          + visibility_config {
              + cloudwatch_metrics_enabled = true
              + metric_name                = "Access-Ristrict-Sample3PathIpRestriction"
              + sampled_requests_enabled   = true
            }
        }

      + visibility_config {
          + cloudwatch_metrics_enabled = true
          + metric_name                = "alb-webacl"
          + sampled_requests_enabled   = true
        }
    }

  # module.waf.aws_wafv2_web_acl_association.waf_association will be created
  + resource "aws_wafv2_web_acl_association" "waf_association" {
      + id           = (known after apply)
      + resource_arn = "arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:loadbalancer/app/waf-test-alb/xxxxxxxxxxxxxxxx"
      + web_acl_arn  = (known after apply)
    }

  # module.waf.aws_wafv2_web_acl_logging_configuration.waflog will be created
  + resource "aws_wafv2_web_acl_logging_configuration" "waflog" {
      + id                      = (known after apply)
      + log_destination_configs = (known after apply)
      + resource_arn            = (known after apply)

      + logging_filter {
          + default_behavior = "DROP"

          + filter {
              + behavior    = "KEEP"
              + requirement = "MEETS_ANY"

              + condition {
                  + action_condition {
                      + action = "BLOCK"
                    }
                }
              + condition {
                  + action_condition {
                      + action = "CAPTCHA"
                    }
                }
              + condition {
                  + action_condition {
                      + action = "COUNT"
                    }
                }
            }
        }
    }

Plan: 8 to add, 0 to change, 0 to destroy.

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── 

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you  
run "terraform apply" now.
PS C:\Users\ユーザー\Documents\Terraform\terraform-dynamic-aws-waf-rules\envs\dev-waf>

terraform apply(途中 yes 入力)

実行コマンド

terraform apply
実行結果(クリックで展開)
PS C:\Users\ユーザー\Documents\Terraform\terraform-dynamic-aws-waf-rules\envs\dev-waf> terraform apply                   

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the    
following symbols:
  + create

Terraform will perform the following actions:

  # module.waf.aws_cloudwatch_log_group.cwlogs will be created
  + resource "aws_cloudwatch_log_group" "cwlogs" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + log_group_class   = (known after apply)
      + name              = "aws-waf-logs-alb-webacl"
      + name_prefix       = (known after apply)
      + retention_in_days = 30
      + skip_destroy      = false
      + tags              = {
          + "Name" = "aws-waf-logs-alb-webacl"
        }
      + tags_all          = {
          + "Name" = "aws-waf-logs-alb-webacl"
        }
    }

  # module.waf.aws_wafv2_ip_set.access_ristrict["access-ristrict-sample2"] will be created
  + resource "aws_wafv2_ip_set" "access_ristrict" {
      + addresses          = [
          + "0.0.0.0/1",
          + "128.0.0.0/1",
        ]
      + arn                = (known after apply)
      + description        = "access-ristrict-sample2-ristrict-ipsets"
      + id                 = (known after apply)
      + ip_address_version = "IPV4"
      + lock_token         = (known after apply)
      + name               = "access-ristrict-sample2-ristrict-ipsets"
      + scope              = "REGIONAL"
      + tags               = {
          + "Name" = "access-ristrict-sample2-ristrict-ipsets"
        }
      + tags_all           = {
          + "Name" = "access-ristrict-sample2-ristrict-ipsets"
        }
    }

  # module.waf.aws_wafv2_ip_set.access_ristrict["access-ristrict-sample3"] will be created
  + resource "aws_wafv2_ip_set" "access_ristrict" {
      + addresses          = [
          + "0.0.0.0/1",
          + "128.0.0.0/1",
        ]
      + arn                = (known after apply)
      + description        = "access-ristrict-sample3-ristrict-ipsets"
      + id                 = (known after apply)
      + ip_address_version = "IPV4"
      + lock_token         = (known after apply)
      + name               = "access-ristrict-sample3-ristrict-ipsets"
      + scope              = "REGIONAL"
      + tags               = {
          + "Name" = "access-ristrict-sample3-ristrict-ipsets"
        }
      + tags_all           = {
          + "Name" = "access-ristrict-sample3-ristrict-ipsets"
        }
    }

  # module.waf.aws_wafv2_rule_group.access_ristrict["access-ristrict-sample2"] will be created
  + resource "aws_wafv2_rule_group" "access_ristrict" {
      + arn         = (known after apply)
      + capacity    = 3
      + description = "access-ristrict-sample2-ristrict-waf-rulegp"
      + id          = (known after apply)
      + lock_token  = (known after apply)
      + name        = "access-ristrict-sample2-ristrict-waf-rulegp"
      + name_prefix = (known after apply)
      + scope       = "REGIONAL"
      + tags_all    = (known after apply)

      + rule {
          + name     = "access-ristrict-sample2-ristrict-rule"
          + priority = 1

          + action {
              + block {
                }
            }

          + statement {
              + and_statement {
                  + statement {
                      + byte_match_statement {
                          + positional_constraint = "STARTS_WITH"
                          + search_string         = "/ristrict/sample2/"

                          + field_to_match {
                              + uri_path {}
                            }

                          + text_transformation {
                              + priority = 0
                              + type     = "NONE"
                            }
                        }
                    }
                  + statement {
                      + not_statement {
                          + statement {
                              + ip_set_reference_statement {
                                  + arn = (known after apply)
                                }
                            }
                        }
                    }
                }
            }

          + visibility_config {
              + cloudwatch_metrics_enabled = true
              + metric_name                = "access-ristrict-sample2-ristrict-rule"
              + sampled_requests_enabled   = true
            }
        }

      + visibility_config {
          + cloudwatch_metrics_enabled = true
          + metric_name                = "access-ristrict-sample2-ristrict-rulegp"
          + sampled_requests_enabled   = true
        }
    }

  # module.waf.aws_wafv2_rule_group.access_ristrict["access-ristrict-sample3"] will be created
  + resource "aws_wafv2_rule_group" "access_ristrict" {
      + arn         = (known after apply)
      + capacity    = 3
      + description = "access-ristrict-sample3-ristrict-waf-rulegp"
      + id          = (known after apply)
      + lock_token  = (known after apply)
      + name        = "access-ristrict-sample3-ristrict-waf-rulegp"
      + name_prefix = (known after apply)
      + scope       = "REGIONAL"
      + tags_all    = (known after apply)

      + rule {
          + name     = "access-ristrict-sample3-ristrict-rule"
          + priority = 1

          + action {
              + block {
                }
            }

          + statement {
              + and_statement {
                  + statement {
                      + byte_match_statement {
                          + positional_constraint = "STARTS_WITH"
                          + search_string         = "/ristrict/sample3/"

                          + field_to_match {
                              + uri_path {}
                            }

                          + text_transformation {
                              + priority = 0
                              + type     = "NONE"
                            }
                        }
                    }
                  + statement {
                      + not_statement {
                          + statement {
                              + ip_set_reference_statement {
                                  + arn = (known after apply)
                                }
                            }
                        }
                    }
                }
            }

          + visibility_config {
              + cloudwatch_metrics_enabled = true
              + metric_name                = "access-ristrict-sample3-ristrict-rule"
              + sampled_requests_enabled   = true
            }
        }

      + visibility_config {
          + cloudwatch_metrics_enabled = true
          + metric_name                = "access-ristrict-sample3-ristrict-rulegp"
          + sampled_requests_enabled   = true
        }
    }

  # module.waf.aws_wafv2_web_acl.web_acl will be created
  + resource "aws_wafv2_web_acl" "web_acl" {
      + application_integration_url = (known after apply)
      + arn                         = (known after apply)
      + capacity                    = (known after apply)
      + description                 = "alb-wabacl"
      + id                          = (known after apply)
      + lock_token                  = (known after apply)
      + name                        = "alb-webacl"
      + scope                       = "REGIONAL"
      + tags                        = {
          + "Name" = "alb-webacl"
        }
      + tags_all                    = {
          + "Name" = "alb-webacl"
        }

      + default_action {
          + allow {
            }
        }

      + rule {
          + name     = "Access-Ristrict-Sample2PathIpRestriction"
          + priority = 1001

          + override_action {
              + none {}
            }

          + statement {
              + rule_group_reference_statement {
                  + arn = (known after apply)
                }
            }

          + visibility_config {
              + cloudwatch_metrics_enabled = true
              + metric_name                = "Access-Ristrict-Sample2PathIpRestriction"
              + sampled_requests_enabled   = true
            }
        }
      + rule {
          + name     = "Access-Ristrict-Sample3PathIpRestriction"
          + priority = 1002

          + override_action {
              + none {}
            }

          + statement {
              + rule_group_reference_statement {
                  + arn = (known after apply)
                }
            }

          + visibility_config {
              + cloudwatch_metrics_enabled = true
              + metric_name                = "Access-Ristrict-Sample3PathIpRestriction"
              + sampled_requests_enabled   = true
            }
        }

      + visibility_config {
          + cloudwatch_metrics_enabled = true
          + metric_name                = "alb-webacl"
          + sampled_requests_enabled   = true
        }
    }

  # module.waf.aws_wafv2_web_acl_association.waf_association will be created
  + resource "aws_wafv2_web_acl_association" "waf_association" {
      + id           = (known after apply)
      + resource_arn = "arn:aws:elasticloadbalancing:ap-northeast-1:スイッチ先AWSアカウントID:loadbalancer/app/waf-test-alb/xxxxxxxxxx"
      + web_acl_arn  = (known after apply)
    }

  # module.waf.aws_wafv2_web_acl_logging_configuration.waflog will be created
  + resource "aws_wafv2_web_acl_logging_configuration" "waflog" {
      + id                      = (known after apply)
      + log_destination_configs = (known after apply)
      + resource_arn            = (known after apply)

      + logging_filter {
          + default_behavior = "DROP"

          + filter {
              + behavior    = "KEEP"
              + requirement = "MEETS_ANY"

              + condition {
                  + action_condition {
                      + action = "BLOCK"
                    }
                }
              + condition {
                  + action_condition {
                      + action = "CAPTCHA"
                    }
                }
              + condition {
                  + action_condition {
                      + action = "COUNT"
                    }
                }
            }
        }
    }

Plan: 8 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

module.waf.aws_wafv2_web_acl_logging_configuration.waflog: Destroying... [id=arn:aws:wafv2:ap-northeast-1:スイッチ先AWSアカウントID:regional/webacl/alb-webacl/cfe7ea2e-b3a7-4aae-8a92-0a034a9b23d1]
module.waf.aws_wafv2_web_acl_logging_configuration.waflog: Destruction complete after 0s
module.waf.aws_cloudwatch_log_group.cwlogs: Destroying... [id=aws-waf-logs-alb-webacl]
module.waf.aws_cloudwatch_log_group.cwlogs: Destruction complete after 1s
module.waf.aws_wafv2_web_acl.web_acl: Destroying... [id=cfe7ea2e-b3a7-4aae-8a92-0a034a9b23d1]
module.waf.aws_wafv2_web_acl.web_acl: Destruction complete after 1s
module.waf.aws_wafv2_rule_group.access_ristrict["access-ristrict-sample2"]: Destroying... [id=72cf5e5c-f461-43d8-98ea-462c86e2434c]
module.waf.aws_wafv2_rule_group.access_ristrict["access-ristrict-sample3"]: Destroying... [id=530e0cf6-aa12-46d7-bdaa-118a6139d09b]
module.waf.aws_wafv2_rule_group.access_ristrict["access-ristrict-sample2"]: Destruction complete after 0s
module.waf.aws_wafv2_rule_group.access_ristrict["access-ristrict-sample3"]: Destruction complete after 3s
module.waf.aws_wafv2_ip_set.access_ristrict["access-ristrict-sample2"]: Destroying... [id=cb701822-9175-447c-9072-d742c1b5d864]
module.waf.aws_wafv2_ip_set.access_ristrict["access-ristrict-sample3"]: Destroying... [id=ad542e96-ab31-46e3-b998-1b2bca116592]
module.waf.aws_wafv2_ip_set.access_ristrict["access-ristrict-sample2"]: Destruction complete after 0s
module.waf.aws_wafv2_ip_set.access_ristrict["access-ristrict-sample3"]: Destruction complete after 3s

Destroy complete! Resources: 7 destroyed.
PS C:\Users\ユーザー\Documents\Terraform\terraform-dynamic-aws-waf-rules\envs\dev-waf> 
PS C:\Users\ユーザー\Documents\Terraform\terraform-dynamic-aws-waf-rules\envs\dev-waf> 
PS C:\Users\ユーザー\Documents\Terraform\terraform-dynamic-aws-waf-rules\envs\dev-waf> terraform apply                   

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the    
following symbols:
  + create

Terraform will perform the following actions:

  # module.waf.aws_cloudwatch_log_group.cwlogs will be created
  + resource "aws_cloudwatch_log_group" "cwlogs" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + log_group_class   = (known after apply)
      + name              = "aws-waf-logs-alb-webacl"
      + name_prefix       = (known after apply)
      + retention_in_days = 30
      + skip_destroy      = false
      + tags              = {
          + "Name" = "aws-waf-logs-alb-webacl"
        }
      + tags_all          = {
          + "Name" = "aws-waf-logs-alb-webacl"
        }
    }

  # module.waf.aws_wafv2_ip_set.access_ristrict["access-ristrict-sample2"] will be created
  + resource "aws_wafv2_ip_set" "access_ristrict" {
      + addresses          = [
          + "0.0.0.0/1",
          + "128.0.0.0/1",
        ]
      + arn                = (known after apply)
      + description        = "access-ristrict-sample2-ristrict-ipsets"
      + id                 = (known after apply)
      + ip_address_version = "IPV4"
      + lock_token         = (known after apply)
      + name               = "access-ristrict-sample2-ristrict-ipsets"
      + scope              = "REGIONAL"
      + tags               = {
          + "Name" = "access-ristrict-sample2-ristrict-ipsets"
        }
      + tags_all           = {
          + "Name" = "access-ristrict-sample2-ristrict-ipsets"
        }
    }

  # module.waf.aws_wafv2_ip_set.access_ristrict["access-ristrict-sample3"] will be created
  + resource "aws_wafv2_ip_set" "access_ristrict" {
      + addresses          = [
          + "0.0.0.0/1",
          + "128.0.0.0/1",
        ]
      + arn                = (known after apply)
      + description        = "access-ristrict-sample3-ristrict-ipsets"
      + id                 = (known after apply)
      + ip_address_version = "IPV4"
      + lock_token         = (known after apply)
      + name               = "access-ristrict-sample3-ristrict-ipsets"
      + scope              = "REGIONAL"
      + tags               = {
          + "Name" = "access-ristrict-sample3-ristrict-ipsets"
        }
      + tags_all           = {
          + "Name" = "access-ristrict-sample3-ristrict-ipsets"
        }
    }

  # module.waf.aws_wafv2_rule_group.access_ristrict["access-ristrict-sample2"] will be created
  + resource "aws_wafv2_rule_group" "access_ristrict" {
      + arn         = (known after apply)
      + capacity    = 3
      + description = "access-ristrict-sample2-ristrict-waf-rulegp"
      + id          = (known after apply)
      + lock_token  = (known after apply)
      + name        = "access-ristrict-sample2-ristrict-waf-rulegp"
      + name_prefix = (known after apply)
      + scope       = "REGIONAL"
      + tags_all    = (known after apply)

      + rule {
          + name     = "access-ristrict-sample2-ristrict-rule"
          + priority = 1

          + action {
              + block {
                }
            }

          + statement {
              + and_statement {
                  + statement {
                      + byte_match_statement {
                          + positional_constraint = "STARTS_WITH"
                          + search_string         = "/ristrict/sample2/"

                          + field_to_match {
                              + uri_path {}
                            }

                          + text_transformation {
                              + priority = 0
                              + type     = "NONE"
                            }
                        }
                    }
                  + statement {
                      + not_statement {
                          + statement {
                              + ip_set_reference_statement {
                                  + arn = (known after apply)
                                }
                            }
                        }
                    }
                }
            }

          + visibility_config {
              + cloudwatch_metrics_enabled = true
              + metric_name                = "access-ristrict-sample2-ristrict-rule"
              + sampled_requests_enabled   = true
            }
        }

      + visibility_config {
          + cloudwatch_metrics_enabled = true
          + metric_name                = "access-ristrict-sample2-ristrict-rulegp"
          + sampled_requests_enabled   = true
        }
    }

  # module.waf.aws_wafv2_rule_group.access_ristrict["access-ristrict-sample3"] will be created
  + resource "aws_wafv2_rule_group" "access_ristrict" {
      + arn         = (known after apply)
      + capacity    = 3
      + description = "access-ristrict-sample3-ristrict-waf-rulegp"
      + id          = (known after apply)
      + lock_token  = (known after apply)
      + name        = "access-ristrict-sample3-ristrict-waf-rulegp"
      + name_prefix = (known after apply)
      + scope       = "REGIONAL"
      + tags_all    = (known after apply)

      + rule {
          + name     = "access-ristrict-sample3-ristrict-rule"
          + priority = 1

          + action {
              + block {
                }
            }

          + statement {
              + and_statement {
                  + statement {
                      + byte_match_statement {
                          + positional_constraint = "STARTS_WITH"
                          + search_string         = "/ristrict/sample3/"

                          + field_to_match {
                              + uri_path {}
                            }

                          + text_transformation {
                              + priority = 0
                              + type     = "NONE"
                            }
                        }
                    }
                  + statement {
                      + not_statement {
                          + statement {
                              + ip_set_reference_statement {
                                  + arn = (known after apply)
                                }
                            }
                        }
                    }
                }
            }

          + visibility_config {
              + cloudwatch_metrics_enabled = true
              + metric_name                = "access-ristrict-sample3-ristrict-rule"
              + sampled_requests_enabled   = true
            }
        }

      + visibility_config {
          + cloudwatch_metrics_enabled = true
          + metric_name                = "access-ristrict-sample3-ristrict-rulegp"
          + sampled_requests_enabled   = true
        }
    }

  # module.waf.aws_wafv2_web_acl.web_acl will be created
  + resource "aws_wafv2_web_acl" "web_acl" {
      + application_integration_url = (known after apply)
      + arn                         = (known after apply)
      + capacity                    = (known after apply)
      + description                 = "alb-wabacl"
      + id                          = (known after apply)
      + lock_token                  = (known after apply)
      + name                        = "alb-webacl"
      + scope                       = "REGIONAL"
      + tags                        = {
          + "Name" = "alb-webacl"
        }
      + tags_all                    = {
          + "Name" = "alb-webacl"
        }

      + default_action {
          + allow {
            }
        }

      + rule {
          + name     = "Access-Ristrict-Sample2PathIpRestriction"
          + priority = 1001

          + override_action {
              + none {}
            }

          + statement {
              + rule_group_reference_statement {
                  + arn = (known after apply)
                }
            }

          + visibility_config {
              + cloudwatch_metrics_enabled = true
              + metric_name                = "Access-Ristrict-Sample2PathIpRestriction"
              + sampled_requests_enabled   = true
            }
        }
      + rule {
          + name     = "Access-Ristrict-Sample3PathIpRestriction"
          + priority = 1002

          + override_action {
              + none {}
            }

          + statement {
              + rule_group_reference_statement {
                  + arn = (known after apply)
                }
            }

          + visibility_config {
              + cloudwatch_metrics_enabled = true
              + metric_name                = "Access-Ristrict-Sample3PathIpRestriction"
              + sampled_requests_enabled   = true
            }
        }

      + visibility_config {
          + cloudwatch_metrics_enabled = true
          + metric_name                = "alb-webacl"
          + sampled_requests_enabled   = true
        }
    }

  # module.waf.aws_wafv2_web_acl_association.waf_association will be created
  + resource "aws_wafv2_web_acl_association" "waf_association" {
      + id           = (known after apply)
      + resource_arn = "arn:aws:elasticloadbalancing:ap-northeast-1:スイッチ先AWSアカウントID:loadbalancer/app/waf-test-alb/xxxxxxxxxx"
      + web_acl_arn  = (known after apply)
    }

  # module.waf.aws_wafv2_web_acl_logging_configuration.waflog will be created
  + resource "aws_wafv2_web_acl_logging_configuration" "waflog" {
      + id                      = (known after apply)
      + log_destination_configs = (known after apply)
      + resource_arn            = (known after apply)

      + logging_filter {
          + default_behavior = "DROP"

          + filter {
              + behavior    = "KEEP"
              + requirement = "MEETS_ANY"

              + condition {
                  + action_condition {
                      + action = "BLOCK"
                    }
                }
              + condition {
                  + action_condition {
                      + action = "CAPTCHA"
                    }
                }
              + condition {
                  + action_condition {
                      + action = "COUNT"
                    }
                }
            }
        }
    }

Plan: 8 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

module.waf.aws_wafv2_ip_set.access_ristrict["access-ristrict-sample2"]: Creating...
module.waf.aws_wafv2_ip_set.access_ristrict["access-ristrict-sample3"]: Creating...
module.waf.aws_wafv2_ip_set.access_ristrict["access-ristrict-sample2"]: Creation complete after 1s [id=xxxxxxxxxx]
module.waf.aws_wafv2_ip_set.access_ristrict["access-ristrict-sample3"]: Creation complete after 1s [id=xxxxxxxxxx]
module.waf.aws_wafv2_rule_group.access_ristrict["access-ristrict-sample3"]: Creating...
module.waf.aws_wafv2_rule_group.access_ristrict["access-ristrict-sample2"]: Creating...
module.waf.aws_wafv2_rule_group.access_ristrict["access-ristrict-sample3"]: Creation complete after 1s [id=xxxxxxxxxx]
module.waf.aws_wafv2_rule_group.access_ristrict["access-ristrict-sample2"]: Creation complete after 1s [id=xxxxxxxxxx]
module.waf.aws_wafv2_web_acl.web_acl: Creating...
module.waf.aws_wafv2_web_acl.web_acl: Creation complete after 1s [id=xxxxxxxxxx]
module.waf.aws_wafv2_web_acl_association.waf_association: Creating...
module.waf.aws_cloudwatch_log_group.cwlogs: Creating...
module.waf.aws_cloudwatch_log_group.cwlogs: Creation complete after 0s [id=aws-waf-logs-alb-webacl]
module.waf.aws_wafv2_web_acl_logging_configuration.waflog: Creating...
module.waf.aws_wafv2_web_acl_logging_configuration.waflog: Creation complete after 0s [id=arn:aws:wafv2:ap-northeast-1:スイッチ先AWSアカウントID:regional/webacl/alb-webacl/xxxxxxxxxx]
module.waf.aws_wafv2_web_acl_association.waf_association: Still creating... [10s elapsed]
module.waf.aws_wafv2_web_acl_association.waf_association: Still creating... [20s elapsed]
module.waf.aws_wafv2_web_acl_association.waf_association: Still creating... [30s elapsed]
module.waf.aws_wafv2_web_acl_association.waf_association: Creation complete after 34s [id=arn:aws:wafv2:ap-northeast-1:スイッチ先AWSアカウントID:regional/webacl/alb-webacl/xxxxxxxxxx,arn:aws:elasticloadbalancing:ap-northeast-1:スイッチ先AWSアカウントID:loadbalancer/app/waf-test-alb/xxxxxxxxxx]

Apply complete! Resources: 8 added, 0 changed, 0 destroyed.
PS C:\Users\ユーザー\Documents\Terraform\terraform-dynamic-aws-waf-rules\envs\dev-waf>

terraform destroy

terraform destroy
実行結果(クリックで展開)
PS C:\Users\ユーザー\Documents\Terraform\terraform-dynamic-aws-waf-rules\envs\dev-waf> terraform destroy
module.waf.aws_wafv2_ip_set.access_ristrict["access-ristrict-sample3"]: Refreshing state... [id=xxxxxxxxxx]
module.waf.aws_wafv2_ip_set.access_ristrict["access-ristrict-sample2"]: Refreshing state... [id=xxxxxxxxxx]
module.waf.aws_wafv2_rule_group.access_ristrict["access-ristrict-sample2"]: Refreshing state... [id=xxxxxxxxxx]
module.waf.aws_wafv2_rule_group.access_ristrict["access-ristrict-sample3"]: Refreshing state... [id=xxxxxxxxxx]
module.waf.aws_wafv2_web_acl.web_acl: Refreshing state... [id=xxxxxxxxxx]
module.waf.aws_cloudwatch_log_group.cwlogs: Refreshing state... [id=aws-waf-logs-alb-webacl]
module.waf.aws_wafv2_web_acl_association.waf_association: Refreshing state... [id=arn:aws:wafv2:ap-northeast-1:スイッチ先AWSアカウントID:regional/webacl/alb-webacl/xxxxxxxxxx,arn:aws:elasticloadbalancing:ap-northeast-1:スイッチ先AWSアカウントID:loadbalancer/app/waf-test-alb/xxxxxxxxxx]
module.waf.aws_wafv2_web_acl_logging_configuration.waflog: Refreshing state... [id=arn:aws:wafv2:ap-northeast-1:スイッチ先AWSアカウントID:regional/webacl/alb-webacl/xxxxxxxxxx]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the    
following symbols:
  - destroy

Terraform will perform the following actions:

  # module.waf.aws_cloudwatch_log_group.cwlogs will be destroyed
  - resource "aws_cloudwatch_log_group" "cwlogs" {
      - arn               = "arn:aws:logs:ap-northeast-1:スイッチ先AWSアカウントID:log-group:aws-waf-logs-alb-webacl" -> null
      - id                = "aws-waf-logs-alb-webacl" -> null
      - log_group_class   = "STANDARD" -> null
      - name              = "aws-waf-logs-alb-webacl" -> null
      - retention_in_days = 30 -> null
      - skip_destroy      = false -> null
      - tags              = {
          - "Name" = "aws-waf-logs-alb-webacl"
        } -> null
      - tags_all          = {
          - "Name" = "aws-waf-logs-alb-webacl"
        } -> null
    }

  # module.waf.aws_wafv2_ip_set.access_ristrict["access-ristrict-sample2"] will be destroyed
  - resource "aws_wafv2_ip_set" "access_ristrict" {
      - addresses          = [
          - "0.0.0.0/1",
          - "128.0.0.0/1",
        ] -> null
      - arn                = "arn:aws:wafv2:ap-northeast-1:スイッチ先AWSアカウントID:regional/ipset/access-ristrict-sample2-ristrict-ipsets/xxxxxxxxxx" -> null
      - description        = "access-ristrict-sample2-ristrict-ipsets" -> null
      - id                 = "xxxxxxxxxx" -> null
      - ip_address_version = "IPV4" -> null
      - lock_token         = "f5b71e81-73ef-44ef-bfe3-219fbb40537a" -> null
      - name               = "access-ristrict-sample2-ristrict-ipsets" -> null
      - scope              = "REGIONAL" -> null
      - tags               = {
          - "Name" = "access-ristrict-sample2-ristrict-ipsets"
        } -> null
      - tags_all           = {
          - "Name" = "access-ristrict-sample2-ristrict-ipsets"
        } -> null
    }

  # module.waf.aws_wafv2_ip_set.access_ristrict["access-ristrict-sample3"] will be destroyed
  - resource "aws_wafv2_ip_set" "access_ristrict" {
      - addresses          = [
          - "0.0.0.0/1",
          - "128.0.0.0/1",
        ] -> null
      - arn                = "arn:aws:wafv2:ap-northeast-1:スイッチ先AWSアカウントID:regional/ipset/access-ristrict-sample3-ristrict-ipsets/xxxxxxxxxx" -> null
      - description        = "access-ristrict-sample3-ristrict-ipsets" -> null
      - id                 = "xxxxxxxxxx" -> null
      - ip_address_version = "IPV4" -> null
      - lock_token         = "c7d96fbe-7963-494a-b98e-6322f9f5bdcc" -> null
      - name               = "access-ristrict-sample3-ristrict-ipsets" -> null
      - scope              = "REGIONAL" -> null
      - tags               = {
          - "Name" = "access-ristrict-sample3-ristrict-ipsets"
        } -> null
      - tags_all           = {
          - "Name" = "access-ristrict-sample3-ristrict-ipsets"
        } -> null
    }

  # module.waf.aws_wafv2_rule_group.access_ristrict["access-ristrict-sample2"] will be destroyed
  - resource "aws_wafv2_rule_group" "access_ristrict" {
      - arn         = "arn:aws:wafv2:ap-northeast-1:スイッチ先AWSアカウントID:regional/rulegroup/access-ristrict-sample2-ristrict-waf-rulegp/xxxxxxxxxx" -> null
      - capacity    = 3 -> null
      - description = "access-ristrict-sample2-ristrict-waf-rulegp" -> null
      - id          = "xxxxxxxxxx" -> null
      - lock_token  = "5d8972fb-fe2e-4a69-8c8e-e6798b742207" -> null
      - name        = "access-ristrict-sample2-ristrict-waf-rulegp" -> null
      - scope       = "REGIONAL" -> null
      - tags        = {} -> null
      - tags_all    = {} -> null

      - rule {
          - name     = "access-ristrict-sample2-ristrict-rule" -> null
          - priority = 1 -> null

          - action {
              - block {
                }
            }

          - statement {
              - and_statement {
                  - statement {
                      - byte_match_statement {
                          - positional_constraint = "STARTS_WITH" -> null
                          - search_string         = "/ristrict/sample2/" -> null

                          - field_to_match {
                              - uri_path {}
                            }

                          - text_transformation {
                              - priority = 0 -> null
                              - type     = "NONE" -> null
                            }
                        }
                    }
                  - statement {
                      - not_statement {
                          - statement {
                              - ip_set_reference_statement {
                                  - arn = "arn:aws:wafv2:ap-northeast-1:スイッチ先AWSアカウントID:regional/ipset/access-ristrict-sample2-ristrict-ipsets/xxxxxxxxxx" -> null
                                }
                            }
                        }
                    }
                }
            }

          - visibility_config {
              - cloudwatch_metrics_enabled = true -> null
              - metric_name                = "access-ristrict-sample2-ristrict-rule" -> null
              - sampled_requests_enabled   = true -> null
            }
        }

      - visibility_config {
          - cloudwatch_metrics_enabled = true -> null
          - metric_name                = "access-ristrict-sample2-ristrict-rulegp" -> null
          - sampled_requests_enabled   = true -> null
        }
    }

  # module.waf.aws_wafv2_rule_group.access_ristrict["access-ristrict-sample3"] will be destroyed
  - resource "aws_wafv2_rule_group" "access_ristrict" {
      - arn         = "arn:aws:wafv2:ap-northeast-1:スイッチ先AWSアカウントID:regional/rulegroup/access-ristrict-sample3-ristrict-waf-rulegp/xxxxxxxxxx" -> null
      - capacity    = 3 -> null
      - description = "access-ristrict-sample3-ristrict-waf-rulegp" -> null
      - id          = "xxxxxxxxxx" -> null
      - lock_token  = "801a03dd-4216-4e23-8020-013a2defbccb" -> null
      - name        = "access-ristrict-sample3-ristrict-waf-rulegp" -> null
      - scope       = "REGIONAL" -> null
      - tags        = {} -> null
      - tags_all    = {} -> null

      - rule {
          - name     = "access-ristrict-sample3-ristrict-rule" -> null
          - priority = 1 -> null

          - action {
              - block {
                }
            }

          - statement {
              - and_statement {
                  - statement {
                      - byte_match_statement {
                          - positional_constraint = "STARTS_WITH" -> null
                          - search_string         = "/ristrict/sample3/" -> null

                          - field_to_match {
                              - uri_path {}
                            }

                          - text_transformation {
                              - priority = 0 -> null
                              - type     = "NONE" -> null
                            }
                        }
                    }
                  - statement {
                      - not_statement {
                          - statement {
                              - ip_set_reference_statement {
                                  - arn = "arn:aws:wafv2:ap-northeast-1:スイッチ先AWSアカウントID:regional/ipset/access-ristrict-sample3-ristrict-ipsets/xxxxxxxxxx" -> null
                                }
                            }
                        }
                    }
                }
            }

          - visibility_config {
              - cloudwatch_metrics_enabled = true -> null
              - metric_name                = "access-ristrict-sample3-ristrict-rule" -> null
              - sampled_requests_enabled   = true -> null
            }
        }

      - visibility_config {
          - cloudwatch_metrics_enabled = true -> null
          - metric_name                = "access-ristrict-sample3-ristrict-rulegp" -> null
          - sampled_requests_enabled   = true -> null
        }
    }

  # module.waf.aws_wafv2_web_acl.web_acl will be destroyed
  - resource "aws_wafv2_web_acl" "web_acl" {
      - arn           = "arn:aws:wafv2:ap-northeast-1:スイッチ先AWSアカウントID:regional/webacl/alb-webacl/xxxxxxxxxx" -> null
      - capacity      = 6 -> null
      - description   = "alb-wabacl" -> null
      - id            = "xxxxxxxxxx" -> null
      - lock_token    = "83122676-7566-4475-af9a-94ccbdbc8931" -> null
      - name          = "alb-webacl" -> null
      - scope         = "REGIONAL" -> null
      - tags          = {
          - "Name" = "alb-webacl"
        } -> null
      - tags_all      = {
          - "Name" = "alb-webacl"
        } -> null
      - token_domains = [] -> null

      - default_action {
          - allow {
            }
        }

      - rule {
          - name     = "Access-Ristrict-Sample2PathIpRestriction" -> null
          - priority = 1001 -> null

          - override_action {
              - none {}
            }

          - statement {
              - rule_group_reference_statement {
                  - arn = "arn:aws:wafv2:ap-northeast-1:スイッチ先AWSアカウントID:regional/rulegroup/access-ristrict-sample2-ristrict-waf-rulegp/xxxxxxxxxx" -> null
                }
            }

          - visibility_config {
              - cloudwatch_metrics_enabled = true -> null
              - metric_name                = "Access-Ristrict-Sample2PathIpRestriction" -> null
              - sampled_requests_enabled   = true -> null
            }
        }
      - rule {
          - name     = "Access-Ristrict-Sample3PathIpRestriction" -> null
          - priority = 1002 -> null

          - override_action {
              - none {}
            }

          - statement {
              - rule_group_reference_statement {
                  - arn = "arn:aws:wafv2:ap-northeast-1:スイッチ先AWSアカウントID:regional/rulegroup/access-ristrict-sample3-ristrict-waf-rulegp/xxxxxxxxxx" -> null
                }
            }

          - visibility_config {
              - cloudwatch_metrics_enabled = true -> null
              - metric_name                = "Access-Ristrict-Sample3PathIpRestriction" -> null
              - sampled_requests_enabled   = true -> null
            }
        }

      - visibility_config {
          - cloudwatch_metrics_enabled = true -> null
          - metric_name                = "alb-webacl" -> null
          - sampled_requests_enabled   = true -> null
        }
    }

  # module.waf.aws_wafv2_web_acl_association.waf_association will be destroyed
  - resource "aws_wafv2_web_acl_association" "waf_association" {
      - id           = "arn:aws:wafv2:ap-northeast-1:スイッチ先AWSアカウントID:regional/webacl/alb-webacl/xxxxxxxxxx,arn:aws:elasticloadbalancing:ap-northeast-1:スイッチ先AWSアカウントID:loadbalancer/app/waf-test-alb/xxxxxxxxxx" -> null    
      - resource_arn = "arn:aws:elasticloadbalancing:ap-northeast-1:スイッチ先AWSアカウントID:loadbalancer/app/waf-test-alb/xxxxxxxxxx" -> null
      - web_acl_arn  = "arn:aws:wafv2:ap-northeast-1:スイッチ先AWSアカウントID:regional/webacl/alb-webacl/xxxxxxxxxx" -> null
    }

  # module.waf.aws_wafv2_web_acl_logging_configuration.waflog will be destroyed
  - resource "aws_wafv2_web_acl_logging_configuration" "waflog" {
      - id                      = "arn:aws:wafv2:ap-northeast-1:スイッチ先AWSアカウントID:regional/webacl/alb-webacl/xxxxxxxxxx" -> null
      - log_destination_configs = [
          - "arn:aws:logs:ap-northeast-1:スイッチ先AWSアカウントID:log-group:aws-waf-logs-alb-webacl",
        ] -> null
      - resource_arn            = "arn:aws:wafv2:ap-northeast-1:スイッチ先AWSアカウントID:regional/webacl/alb-webacl/xxxxxxxxxx" -> null

      - logging_filter {
          - default_behavior = "DROP" -> null

          - filter {
              - behavior    = "KEEP" -> null
              - requirement = "MEETS_ANY" -> null

              - condition {
                  - action_condition {
                      - action = "BLOCK" -> null
                    }
                }
              - condition {
                  - action_condition {
                      - action = "CAPTCHA" -> null
                    }
                }
              - condition {
                  - action_condition {
                      - action = "COUNT" -> null
                    }
                }
            }
        }
    }

Plan: 0 to add, 0 to change, 8 to destroy.

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

module.waf.aws_wafv2_web_acl_association.waf_association: Destroying... [id=arn:aws:wafv2:ap-northeast-1:スイッチ先AWSアカウントID:regional/webacl/alb-webacl/xxxxxxxxxx,arn:aws:elasticloadbalancing:ap-northeast-1:スイッチ先AWSアカウントID:loadbalancer/app/waf-test-alb/xxxxxxxxxx]
module.waf.aws_wafv2_web_acl_logging_configuration.waflog: Destroying... [id=arn:aws:wafv2:ap-northeast-1:スイッチ先AWSアカウントID:regional/webacl/alb-webacl/xxxxxxxxxx]
module.waf.aws_wafv2_web_acl_logging_configuration.waflog: Destruction complete after 0s
module.waf.aws_cloudwatch_log_group.cwlogs: Destroying... [id=aws-waf-logs-alb-webacl]
module.waf.aws_cloudwatch_log_group.cwlogs: Destruction complete after 0s
module.waf.aws_wafv2_web_acl_association.waf_association: Destruction complete after 2s
module.waf.aws_wafv2_web_acl.web_acl: Destroying... [id=xxxxxxxxxx]
module.waf.aws_wafv2_web_acl.web_acl: Destruction complete after 1s
module.waf.aws_wafv2_rule_group.access_ristrict["access-ristrict-sample2"]: Destroying... [id=xxxxxxxxxx]
module.waf.aws_wafv2_rule_group.access_ristrict["access-ristrict-sample3"]: Destroying... [id=xxxxxxxxxx]
module.waf.aws_wafv2_rule_group.access_ristrict["access-ristrict-sample2"]: Destruction complete after 1s
module.waf.aws_wafv2_rule_group.access_ristrict["access-ristrict-sample3"]: Destruction complete after 1s
module.waf.aws_wafv2_ip_set.access_ristrict["access-ristrict-sample3"]: Destroying... [id=xxxxxxxxxx]
module.waf.aws_wafv2_ip_set.access_ristrict["access-ristrict-sample2"]: Destroying... [id=xxxxxxxxxx]
module.waf.aws_wafv2_ip_set.access_ristrict["access-ristrict-sample2"]: Destruction complete after 0s
module.waf.aws_wafv2_ip_set.access_ristrict["access-ristrict-sample3"]: Destruction complete after 0s

Destroy complete! Resources: 8 destroyed.
PS C:\Users\ユーザー\Documents\Terraform\terraform-dynamic-aws-waf-rules\envs\dev-waf>

おわりに

私の端末は Windows 11 であり AWSume を使いたくても、まずインストールのための pipxpip を使うのが面倒!と思っていたので、朗報でした。
色々試行錯誤中ですが、一旦は今の環境でやりたいことができるようにセットアップできました。

ここまで設定しておいてアレですが、WSL で開発環境を Linux に寄せてしまう方が幸せになれるような気もしています。

この記事が Windows ユーザーの皆様のお役に立てば幸いです。

参考

脚注

  1. 私は Git for Windows に梱包されている Git Bash(MINGW64)で tfenv をインストールし任意のバージョンの Terraform をインストールしてから無理やり Windows の環境変数で terraform.exe へのパスを通す(terraform.exe は "C:\Users\ユーザー\.tfenv\versions\<任意のバージョン>" 配下にありました)という力業を実施しています。もっとスマートな方法があるのでは?と思っています。
  2. 追記:弊社メンバーが Windows 用の tfenv を作成しているので参考情報として記載します。PowerShell版の tfenv(のようなもの) をつくってみた | DevelopersIO https://dev.classmethod.jp/articles/i-published-powrshell-module-tfalias-like-tfenv/