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回やればイメージがつくから実践は大事だねぇ(´Д`)