kakakakakku blog

Weekly Tech Blog: Keep on Learning!

Terraform: AWS WAF で Basic 認証を実装する

AWS WAF を使ってアプリケーションに Basic 認証を設定できる🔒️Basic 認証のセキュリティレベルを理解した上で一時的な社内用途などで使いたいという場面はあると思う.

今回は AWS WAF + ALB(固定レスポンス)という簡単な組み合わせを Terraform で実装して試す.

準備

base64 コマンドでエンコードして Basic 認証の値を作っておく.

$ echo -n 'user:password' | base64
dXNlcjpwYXNzd29yZA==

👾 variables.tf

Basic 認証の値は Terraform コードには直接実装せず variable として渡す.

variable "basic_auth_base64" {
  type      = string
  sensitive = true
}

👾 waf.tf

次は aws_wafv2_web_acl リソースを使って AWS WAF の Web ACL sandbox-waf を実装する.ポイントは Authorization ヘッダーに Basic xxx という値が設定されていなかったら AWS WAF で 401 Unauthorized を返してブロックするところ.visibility_config などは必要最低限の実装にしてるので適宜修正して OK👌

resource "aws_wafv2_web_acl" "main" {
  name  = "sandbox-waf"
  scope = "REGIONAL"

  default_action {
    allow {}
  }

  visibility_config {
    cloudwatch_metrics_enabled = true
    metric_name                = "sandbox-waf"
    sampled_requests_enabled   = true
  }

  rule {
    name     = "basic-auth"
    priority = 1

    action {
      block {
        custom_response {
          response_code = 401
          response_header {
            name  = "www-authenticate"
            value = "Basic"
          }
        }
      }
    }

    statement {
      not_statement {
        statement {
          byte_match_statement {
            positional_constraint = "EXACTLY"
            search_string         = "Basic ${var.basic_auth_base64}"

            field_to_match {
              single_header {
                name = "authorization"
              }
            }

            text_transformation {
              priority = 0
              type     = "NONE"
            }
          }
        }
      }
    }

    visibility_config {
      cloudwatch_metrics_enabled = true
      metric_name                = "basic-auth"
      sampled_requests_enabled   = true
    }
  }
}

👾 alb.tf

最後に AWS WAF を紐付ける ALB sandbox-alb を実装する.今回はサンプルとして固定レスポンスにした.AWS WAF と ALB の紐付けには aws_wafv2_web_acl_association リソースを使う.

resource "aws_lb" "main" {
  name               = "sandbox-alb"
  internal           = false
  load_balancer_type = "application"
  security_groups = [
    "sg-xxxxxxxx"
  ]
  subnets = [
    "subnet-xxxxxxxx",
    "subnet-xxxxxxxx",
  ]

  drop_invalid_header_fields = true
}

resource "aws_lb_listener" "http" {
  load_balancer_arn = aws_lb.main.arn
  port              = "80"
  protocol          = "HTTP"

  default_action {
    type = "fixed-response"

    fixed_response {
      content_type = "text/plain"
      message_body = "Hello!"
      status_code  = "200"
    }
  }
}

resource "aws_wafv2_web_acl_association" "alb" {
  resource_arn = aws_lb.main.arn
  web_acl_arn  = aws_wafv2_web_acl.main.arn
}

動作確認

イイ感じ❗️