AR ホームベーカリー

オイラのアウトプット用ホームベーカリー!

Terraform から binbashar/waf-owasp/aws を削除しようとしたら出来なかったので、 terraform state rm で管理外にした

WAF の module

WAF を一部 Terraform 管理下でテスト導入していた (BFF に組み込み評価中) のだけど、利用していた binbashar/waf-owasp/aws がもうメンテしないっぽいので、順次削除することにした。

DEPRECATION NOTICE: This module will be not longer maintain because there are other Terraform modules that support these features based on ´wafv2´ Managed rules for AWS Web Application Firewall

registry.terraform.io

削除する

だいたい Terraform から記述削除して apply したら消えるでしょ! という感じで作業。

cloudfront.tf
resource "aws_cloudfront_distribution" "example" {

...

# WAF 利用の記述を削除する
-  web_acl_id = module.waf_global_test.web_acl_id

...

}
waf.tf

評価中なので、動作がブロックされると困るからと全部 COUNT 動作としていた。

# WAF 利用の記述を削除する
-  module "waf_global_test" {
-      source = "git::github.com:binbashar/terraform-aws-waf-owasp.git//modules/waf-global?ref=v1.0.17"
-  
-      # Just a prefix to add some level of organization
-      waf_prefix = "${var.prefix}-waf-cloudfront"
-  
-      # List of IPs that are blacklisted
-      blacklisted_ips = []
-  
-      # List of IPs that are allowed to access admin pages
-      admin_remote_ipset = []
-  
-      # By default seted to COUNT for testing in order to avoid service affection; when ready, set it to BLOCK
-      rule_size_restriction_action_type   = "COUNT"
-      rule_sqli_action                    = "COUNT"
-      rule_xss_action                     = "COUNT"
-      rule_lfi_rfi_action                 = "COUNT"
-      rule_ssi_action_type                = "COUNT"
-      rule_auth_tokens_action             = "COUNT"
-      rule_admin_access_action_type       = "COUNT"
-      rule_php_insecurities_action_type   = "COUNT"
-      rule_csrf_action_type               = "COUNT"
-      rule_blacklisted_ips_action_type    = "COUNT"
-  }

反映する

plan して apply。

module.waf.〜 削除される一覧が出るけど、長すぎて標準出力からはみ出るのでリダイレクトさせる。 特にエラーはないようだ。

❯ terraform plan > ./delete.txt

実行する。

❯ terraform apply

#=> module.waf_global_test.aws_waf_byte_match_set.match_admin_url (destroy): 1 error(s) occurred:
#=>   〜 WAFReferencedItemException: This entity is still referenced by other entities.

ンガーッ!!

ナンデ?

という訳でザッとググった、こちとら Terraform アカチャンゆえな。

github.com

github.com

どうも依存関係を考慮できない? っぽいのかな、もういちど作り直して、waf のリソースに create_before_destroy つけてやれば良さそうっぽい。

I just hit this issue today. A simple lifecycle block on the aws_wafregional_rule seems to have done the trick:

lifecycle {
   create_before_destroy = true
 }

コメント兄貴サンキュー!

github.com

とはいえ、もう半分以上リソース削除は実行されていて、「ここから復元すんの……?」というダルさとなにか発生した時の面倒臭さ、というのが勝ったので、別の方法で回避した。

terraform state rm

terraform state rm コマンドを利用すると、リソースを管理下から外す事ができる。 この際、管理下から外れたリソースには削除などは実行されない。

コレ本当に Terraform の管理から外れるだけなので、今回みたいにコード中から削除を伴う変更でコケた時は、 state から除外してしまうのが一番マルいと思う。

zenn.dev

というわけで、コケたリソースを調べて全部順番に state から外した。

ダメだったのは以下。

terraform state rm module.waf_global_test.aws_waf_byte_match_set.match_admin_url
terraform state rm module.waf_global_test.aws_waf_byte_match_set.match_auth_tokens
terraform state rm module.waf_global_test.aws_waf_byte_match_set.match_csrf_method
terraform state rm module.waf_global_test.aws_waf_byte_match_set.match_php_insecure_uri
terraform state rm module.waf_global_test.aws_waf_byte_match_set.match_php_insecure_var_refs
terraform state rm module.waf_global_test.aws_waf_byte_match_set.match_rfi_lfi_traversal
terraform state rm module.waf_global_test.aws_waf_byte_match_set.match_ssi
terraform state rm module.waf_global_test.aws_waf_ipset.admin_remote_ipset
terraform state rm module.waf_global_test.aws_waf_ipset.blacklisted_ips
terraform state rm module.waf_global_test.aws_waf_rule.detect_admin_access
terraform state rm module.waf_global_test.aws_waf_rule.detect_bad_auth_tokens
terraform state rm module.waf_global_test.aws_waf_rule.detect_blacklisted_ips
terraform state rm module.waf_global_test.aws_waf_rule.detect_php_insecure
terraform state rm module.waf_global_test.aws_waf_rule.detect_rfi_lfi_traversal
terraform state rm module.waf_global_test.aws_waf_rule.detect_ssi
terraform state rm module.waf_global_test.aws_waf_rule.enforce_csrf
terraform state rm module.waf_global_test.aws_waf_rule.mitigate_sqli
terraform state rm module.waf_global_test.aws_waf_rule.mitigate_xss
terraform state rm module.waf_global_test.aws_waf_rule.restrict_sizes
terraform state rm module.waf_global_test.aws_waf_size_constraint_set.csrf_token_set
terraform state rm module.waf_global_test.aws_waf_size_constraint_set.size_restrictions
terraform state rm module.waf_global_test.aws_waf_sql_injection_match_set.sql_injection_match_set
terraform state rm module.waf_global_test.aws_waf_web_acl.waf_acl
terraform state rm module.waf_global_test.aws_waf_xss_match_set.xss_match_set

これで無事 Terraform 上では削除できない module.waf. シリーズが認識されなくなったので、再度 terraform apply して各 Cloudfront の Distribution から waf を外して完了。 お疲れ様でした。

後処理

前述の通り terraform state rm は実リソースに影響を及ぼさないので、 AWS 上には上記の module.waf. シリーズが一部残っている。 これはあとで ManagementConsole から手動で削除するようにしましょう。

おまけ

apply で削除できなかった WAF のリソースは、 -target で単独指定して削除しようとすると Route53 やら複数リソースを破壊する、みたいな状態になっていて「ナンデー!?」という状態だったので、今回はこのように対応した。

確認と plan 実行大事、とは思うが、マジでなんで Route53 を吹き飛ばす必要があったんだ……? と謎が残ってしまった。

一応 OWASP Top10 対応のルール、 Cloudformation ならザッと利用できるらしいのだが、こういうのあるとヘタに module 使わずに自分で組んでメンテした方がマシだなー、となる。 ウーン。