あめがえるのITブログ

頑張りすぎない。ほどほどに頑張るブログ。

AWS WAF+ALB+EC2の環境を作成し、WAFでIPブロックを設定してみた


WAFを使った環境構築案件が増えそうなのでお勉強してみた。

やること

terraformでWAF+ALB+EC2の環境を作成し、その後接続元のIPを制限する設定を入れ挙動を確認する。

環境

接続元 ⇒ AWS WAF ⇒ ALB ⇒ EC2(Nginx)

実践!

1.環境作成

# vi main.tf
provider "aws" {
  region = "ap-northeast-1"
  profile = "testvault"
}

variable "env" {
  default = {
    env_name = "test"
    vpc_cidr = "10.0.0.0/16"
    sb_az1a = "ap-northeast-1a"
    sb_az1a_cidr = "10.0.1.0/24"
    sb_az1c = "ap-northeast-1c"
    sb_az1c_cidr = "10.0.2.0/24"
  }
}

### VPC
resource "aws_vpc" "vpc" {
    cidr_block = "${var.env.vpc_cidr}"
    tags = {
        Name = "${var.env.env_name}_vpc"
    }
}

### Subnet
resource "aws_subnet" "public_1a" {
  vpc_id = "${aws_vpc.vpc.id}"
  availability_zone = "${var.env.sb_az1a}"
  cidr_block        = "${var.env.sb_az1a_cidr}"
  tags = {
    Name = "${var.env.env_name}_public_1a"
  }
}

resource "aws_subnet" "public_1c" {
  vpc_id = "${aws_vpc.vpc.id}"
  availability_zone = "${var.env.sb_az1c}"
  cidr_block        = "${var.env.sb_az1c_cidr}"
  tags = {
    Name = "${var.env.env_name}_public_1c"
  }
}

### InternetGateway
resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.vpc.id

  tags = {
    Name = "${var.env.env_name}_igw"
  }
}

### RouteTable
resource "aws_route_table" "public" {
  vpc_id = aws_vpc.vpc.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.igw.id
  }

  tags = {
    Name = "${var.env.env_name}_public_route_table"
  }
}

resource "aws_route_table_association" "public_1a" {
  subnet_id      = aws_subnet.public_1a.id
  route_table_id = aws_route_table.public.id
}

resource "aws_route_table_association" "public_1c" {
  subnet_id      = aws_subnet.public_1c.id
  route_table_id = aws_route_table.public.id
}

### SecurityGroup(ALB)
resource "aws_security_group" "example_alb_sg" {
  name        = "example_alb_sg"
  vpc_id      = aws_vpc.vpc.id
}

resource "aws_security_group_rule" "ingress_alb_http" {
  type        = "ingress"
  from_port   = 80
  to_port     = 80
  protocol    = "tcp"
  cidr_blocks = ["0.0.0.0/0"]
  security_group_id = aws_security_group.example_alb_sg.id
}

resource "aws_security_group_rule" "egress_alb_all" {
  type        = "egress"
  from_port   = 0
  to_port     = 0
  protocol    = "-1"
  cidr_blocks = ["0.0.0.0/0"]
  security_group_id = aws_security_group.example_alb_sg.id
}

### SecurityGroup(EC2)
resource "aws_security_group" "example_ec2_sg" {
  name        = "example_ec2_sg"
  vpc_id      = aws_vpc.vpc.id
}

resource "aws_security_group_rule" "ingress_ec2_http" {
  type        = "ingress"
  from_port   = 80
  to_port     = 80
  protocol    = "tcp"
  cidr_blocks = ["0.0.0.0/0"]
  security_group_id = aws_security_group.example_ec2_sg.id
}

resource "aws_security_group_rule" "ingress_ec2_ssh" {
  type        = "ingress"
  from_port   = 22
  to_port     = 22
  protocol    = "tcp"
  cidr_blocks = ["0.0.0.0/0"]
  security_group_id = aws_security_group.example_ec2_sg.id
}

resource "aws_security_group_rule" "egress_ec2_all" {
  type        = "egress"
  from_port   = 0
  to_port     = 0
  protocol    = "-1"
  cidr_blocks = ["0.0.0.0/0"]
  security_group_id = aws_security_group.example_ec2_sg.id
}

### IAM Role(EC2)
resource "aws_iam_role" "example-ec2-ssm-role" {
  name               = "example-ec2-ssm-role"
  assume_role_policy = data.aws_iam_policy_document.example-ec2-assume-role.json
}

data "aws_iam_policy_document" "example-ec2-assume-role" {
  statement {
    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = ["ec2.amazonaws.com"]
    }
  }
}

data "aws_iam_policy" "example-ec2-policy_ssm_managed_instance_core" {
  arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}

resource "aws_iam_role_policy_attachment" "example-ec2-ssm_managed_instance_core" {
  role       = aws_iam_role.example-ec2-ssm-role.name
  policy_arn = data.aws_iam_policy.example-ec2-policy_ssm_managed_instance_core.arn
}

resource "aws_iam_instance_profile" "example-ec2-profile" {
  name = "example-ec2-profile"
  role = aws_iam_role.example-ec2-ssm-role.name
}

### EC2
resource "aws_instance" "example" {
  ami           = "ami-06180cd4edb6844d2"
  instance_type = "t2.micro"
  subnet_id = aws_subnet.public_1a.id
  security_groups = [aws_security_group.example_ec2_sg.id]
  associate_public_ip_address = true
  iam_instance_profile = aws_iam_instance_profile.example-ec2-profile.name

  user_data = <<-EOF
                #!/bin/bash
                sudo yum update -y
                sudo amazon-linux-extras install epel -y
                sudo yum install nginx -y
                sudo systemctl start nginx
                sudo systemctl enable nginx
              EOF
              
  tags = {
    Name = "example-instance"
  }
}

### ALB
resource "aws_alb" "example" {
  name               = "example-lb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.example_alb_sg.id]
  subnets = [aws_subnet.public_1a.id, aws_subnet.public_1c.id]
  enable_deletion_protection = false

  enable_http2 = true
  idle_timeout = 60
  ip_address_type = "ipv4"

  enable_cross_zone_load_balancing = true
}

resource "aws_alb_listener" "front_end" {
  load_balancer_arn = aws_alb.example.arn
  port              = "80"
  protocol          = "HTTP"

  default_action {
    type             = "forward"
    target_group_arn = aws_alb_target_group.example.arn
  }
}

### TargetGroup
resource "aws_alb_target_group" "example" {
  name     = "example-tg"
  port     = 80
  protocol = "HTTP"
  vpc_id   = aws_vpc.vpc.id
}

resource "aws_alb_target_group_attachment" "example" {
  target_group_arn = aws_alb_target_group.example.arn
  target_id        = aws_instance.example.id
}

### WAF
resource "aws_wafv2_web_acl" "example" {
  name        = "example-waf"
  description = "Example WAF for ALB"
  scope       = "REGIONAL"

  default_action {
    allow {}
  }

  rule {
    name     = "sample-rule"
    priority = 1

    action {
      block {}
    }

    statement {
      ip_set_reference_statement {
        arn = aws_wafv2_ip_set.example.arn
      }
    }
    
    visibility_config {
      cloudwatch_metrics_enabled = false
      metric_name                = "sampleRule"
      sampled_requests_enabled   = false
    }
  }

  visibility_config {
    cloudwatch_metrics_enabled = false
    metric_name                = "exampleAcl"
    sampled_requests_enabled   = false
  }
}

resource "aws_wafv2_ip_set" "example" {
  name               = "example-ip-set"
  description        = "Example IP set for WAF"
  scope              = "REGIONAL"
  ip_address_version = "IPV4"

  addresses = ["1.2.3.4/32"]
}

### WAFとALBの関連付け
resource "aws_wafv2_web_acl_association" "example" {
  web_acl_arn = aws_wafv2_web_acl.example.arn
  resource_arn = aws_alb.example.arn
}


2.コード実行

# terraform plan
# terraform apply


3.接続
※接続できることを確認


4.接続元のグローバルIP確認
※cmanで確認
https://www.cman.jp/network/support/go_access.cgi


5.IP制限
5-1.[WAF]-[IPSets]

5-2.リジョンが[Asia Pacific (Tokyo)]となっていることを確認し、[example-ip-set]を押下

5-3.[Add IP address]を押下

5-4.4で確認した接続元のグローバルIPを設定

5-5.[Add]


6.接続
※「403 Forbidden」が返ることを確認



感想

1回やればイメージがつくから実践は大事だねぇ(´Д`)