あきろぐ

いろいろめもするよ🐈🐈🐈

Terraform v0.12からv0.15にupgradeするときにつまったところ

やっとTerraformのアップグレードに手をつけました。 そのときにつまったときのメモを残しておきます。

リソースに存在しない属性がサポートされていない

aws_codedeploy_appリソースに存在しない属性がサポートされていないというエラーが0.13にアップグレードしたときにでました。 terraform state show aws_codedeploy_app.testで属性を確認してもunique_idは存在していません。 色々と調べたところ、AWSプロバイダv3のバグっぽかったので、AWSプロバイダを3.24->3.50.0まであげることで解決しました。

Instance aws_codedeploy_app.test data could not be decoded from the state:
unsupported attribute "unique_id".

github.com

プロバイダアドレスがレガシーで無効

terraform 0.13upgradeコマンドを実行しているのに、以下のエラーがでました。

Error: Invalid legacy provider address
This configuration or its associated state refers to the unqualified provider "aws".
You must complete the Terraform 0.13 upgrade process before upgrading to later versions.

よくよくUpgradeガイドを見てみると、v0.13以前とv0.14移行だとTerraformのステートスナップショットのフォーマットが異なるらしく、一度v0.13でterraform applyコマンドを差分がなくても実行しておく必要がありました。 このコマンドを実行し、v0.14にあげると上記のエラーは消えました。

Terraform v0.14 does not support legacy Terraform state snapshot formats from prior to Terraform v0.13, so before upgrading to Terraform v0.14 you must have successfully run terraform apply at least once with Terraform v0.13 so that it can complete its state format upgrades.

www.terraform.io

ignore_changesが無視されてリソースを削除しようとする

これは、v0.13->v.014にアップグレードするときに遭遇したエラーです。こちらも調べたところv0.14.0のバグでした。 ignore_changesのマップキーが複数存在すると、一部がignore_changesの対象にならないっぽいです。 v0.14.1のbug fixによってこの問題は解消されているので、アップグレードすることで解決しました。

github.com

AWS WAFv2導入でつまずいた&考慮したほうがいいところ(rate limit編)

概要

AWS WAFv2を実際に使って検証したので、その際につまずいたところや考慮したほうがいいところなどまとめます。

今回はレートベースのルールを使ってリクエストの発生元の IP アドレスが同一のものからリクエストが閾値以上になったらブロックする設定にしました。 レートベースのルールは、5分間あたり100リクエストから閾値に設定することが可能となっているので、低頻度のクローラー対策にも対応できます。 aws.amazon.com

構成

今回はWAFをCloudfrontにアタッチする想定で検証しました。 AWSリソースは、Terraformでコード管理します。 f:id:akngo22:20210707211920p:plain

Terraform

Terraformコードサンプルはこちらです。WAF Classicのときよりシンプルに設定が書けるようになっています。

github.com

今回はCloudfrontにWAFをアタッチするので、aws_wafv2_web_aclリソースのprovider設定をprovider = aws.eastするのを忘れないようにしましょう。 忘れがちなのですが、WAFのログ設定をするときも同じくproviderはaws.eastにする必要があるので注意です。

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2_web_acl_logging_configuration

つまずいたところ

デフォルトのアクションをBlockにしたままだった

本当に些細な部分を見落としていました。WebACLのアクションは、WAFをアタッチしたときのデフォルトのアクションとルール上のアクションは分けて設定するのですが、デフォルトアクションをBlockにしたままCloudfrontにアタッチしてしまったので、反映完了後ページ閲覧ができず403エラーが返ってくるようになっていました。

デフォルトのアクションがBlockのままだとルールが適用されない場合にアクセスがブロックされる設定になっているので、デフォルトアクションはAllowでルール上でBlockアクションを選択する必要があります。

docs.aws.amazon.com

考慮したほうがいいこと

既に運用中のサービスに適用する場合は、まずCountアクションで様子見する

運用中のサービスが急に閲覧できなくなるといった恐ろしい事象をひかないためにも、一度デフォルトアクションはAllow、ルール上のアクションはCountにして様子見したほうがいいと思います。WAFのリソース反映直後は、ルールが実際に適用されるまでにタイムラグがあるらしいので一旦寝かしておくと良さそうです。 1日程度様子見すると、ルールにひっかかったIPアドレスがSampledRequestで確認できるので、これらが問題なクローラーかどうか確認できると思います。(WebACLのルールでsampled_requests_enabledを有効にすれば確認できます)

AWS CLIを使ってカウントされたざっと取り出すこともできます。 ※CLI使う時もregionオプションで--region us-east-1を指定する必要があります

aws wafv2 get-sampled-requests --web-acl-arn <arn> --rule-metric-name <rule-name> --scope CLOUDFRONT --time-window StartTime=yyyy-mm-ddThh:mmZ,EndTime=yyyy-mm-ddThh:mmZ --max-items 500 --region us-east-1 | jq -r .SampledRequests[].Request.ClientIP | sort | uniq > ip.txt

docs.aws.amazon.com

閾値しきい値に設定する場合は、正規のクローラーがブロックされないか確認する

既にサービスを運用中であれば、Googlebotからのリクエストがサイトに来ていると思うので、収集しているログからGooglebotの頻度がどの程度が念の為に確認しておくと良いと思います。

公式ドキュメントにUserAgentの文字列が記載されているので、ログ検索すればある程度Googlebotからどれくらいの頻度でリクエストが来ているのか、設定しようとしているルールの閾値にひっかからないか確認しておきましょう。 developers.google.com

閾値にもタイムラグがある

WebACLのルールの検証をする際に、何回目からリクエストブロックされ403エラーがでるのか検証したのですが、閾値きっかりにブロックされることはありませんでした。

1秒間隔でリクエストを同一IPから送り続けたところ、約30-50回程度閾値から上回った値で403エラーが返りました。1秒間隔より短い頻度でリクエストを送ると閾値から約100回程度上回った値でないとブロックされなかったので、高頻度になるとタイムラグが大きくなる可能性がありそうです。

おわり!

aws-vaultコマンドのエラー対応

こんにちは。 久しぶりにブログ書きます。

aws-vaultコマンド便利ですよね。 色々触っていたらエラー吐くようになったので調査したときのログです。

今回のエラー

雑な意訳:ネストに気をつけてね。$AWS_VAULTを強制的にアンセットして。 なにこれ?

aws-vault: error: aws-vault sessions should be nested with care, unset $AWS_VAULT to force

エラーに従って、アンセットしましたが、解決できず。

$ unset $AWS_VAULT
bash: unset: `xxx': not a valid identifier

有効な識別子じゃないといわれておる。

Issueを見ましたが、特に情報なかった。

github.com

解決策

ソースコードを見ました。 上記のエラーが出るのは環境変数AWS_VAULTに何かしら値が入っているときです。

# exec.goを一部抜粋
    if os.Getenv("AWS_VAULT") != "" {
        return fmt.Errorf("aws-vault sessions should be nested with care, unset $AWS_VAULT to force")
    }

github.com

つまり、AWS-VAULTの値をクリアしてあげればよさそうですね。

$ AWS_VAULT=""
$ echo $AWS_VAULT

これでエラーは解決しました。おわり。

ALBのヘルスチェックに失敗するときに確認すること

概要

ALBのヘルスチェックにハマったので、そのときに見直すところのメモ。

構成

  • ALB
  • ECS
    • Nignxコンテナ
    • Railsコンテナ

確認

ヘルスチェックのエンドポイントが間違っていないか

ALBのターゲットグループに設定するヘルスチェックのエンドポイントが間違っていないか確認する。単純にtypoなのか、ヘルスチェック用のエンドポイントを用意していないのか見直す。 自分がヘルスチェック用エンドポイントを作成している場合は気がつきやすいが、そうでない場合は開発者に確認しておく。/healthだと思っていたが実は/readme.txtだったなど。。。 ヘルスチェックのエンドポイントが間違っていないことが分かったら、curlコマンドでhttpレスポンスコードがちゃんと200を返しているか確認してみる。

# Railsコンテナ内で実行
$ curl localhost:3000/healthcheck -H 'Host:<your domain name>' -I

Railsコンテナからのレスポンスが問題なければ、Nginxコンテナ経由でエンドポイントにリクエスト送ってちゃんと正常なレスポンスを返すか確認する。ここで上手くいかないとNginxの設定がミスっている可能性があるので、設定ファイルを見直す。 Nginxコンテナの中にALBのヘルスチェック結果のログが吐かれているのでそれも確認しておく。(ヘルスチェックログ:/var/log/access.log

# Nginxコンテナ内で実行
$ curl localhost:80/healthcheck -H 'Host:<your domain name>' -I

続いてコンテナが乗っているEC2インスタンスからヘルスチェックのエンドポイントにリクエストを送ってみる。リクエストを送るポートはdocker psコマンドで確認する。

# EC2インスタンス内で実行
$ curl localhost:xxxx/healthcheck -H 'Host:<your domain name>' -I

ECSクラスタのセキュリィグループが間違っていないか

gateway timeout 504がヘルスチェックで返ってくる場合は、ECSコンテナのセキュリティグループにてALBに設定しているセキュリィグループを許可していない可能性がある。ここでALBからのリクエストが許可されていないとそもそもEC2インスタンスにリクエストが届かないので504エラーが返ってくる。

ヘルスチェックのタイムアウト時間が短すぎないか

コンテナが立ち上がるまでの処理に時間がかかっていると、コンテナが立ち上がる前にヘルスチェックが失敗と見なされてしまうので起動時に重い処理をentrypoint.shで実行している場合は、ALBのタイムアウト時間を長めにとっておく。

おしまい