GlobalAcceleratorで接続元IPを制御する

# 概要と注意点
GlobalAcceleratorのトラフィックが経由するNetworkInterfacesはエンドポイントにトラフィックをルーティングするため、エンドポイントが存在するサブネットごとに1つずつ、NetworkInterfacesを作成します。
その際に、SecuryGroupも作成され、NetworkInterfacesにアタッチされます。
## 注意点1
任意のVPC内のエンドポイント用に作成されたNetworkInterfacesは、NetworkInterfacesが関連付けられているサブネットに関係なく、すべて同じセキュリティグループを使用するという点です。
また、このSecuryGroupのInboudルールを編集することはシステムによって禁止されてはいないですが、編集した結果、エンドポイントに異常が起きることがあるようです。
そもそもですが、複数のNetworkInterfacesが同一のSecuryGroupを使用するという仕様も気持ち悪いので、任意のSecuryGroupを作成し、それをNetworkInterfacesにアタッチすしたほうがいいと考えます。そうすることでInboundルールも適宜変更が可能になります。
## 注意点2
GlobalAccelerator作成時に作成されたSecuryGroupはterraform showでもIDがわからないため、別途APIで調べます。

```sh
$ aws ec2 describe-security-groups --filters Name=description,Values="GlobalAccelerator configured SecurityGroup"
```

```tf
data "aws_security_group" "sample" {
  filter {
    name   = "description"
    values = ["GlobalAccelerator configured SecurityGroup"]
  }
}
```

# イメージ
![Untitled (17).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58788/89f0a3a2-5565-f8ed-29ed-edf41b8a47bd.png)

# 環境
```sh
aws-cli/2.1.38 Python/3.8.8 Darwin/19.6.0 exe/x86_64 prompt/off

Terraform v1.0.3
on darwin_amd64
```

# 設定
```globalaccelerator_accelerator.tf
resource "aws_globalaccelerator_accelerator" "sample_accelerator" {
  provider        = aws.oregon
  name            = "sample-accelerator"
  ip_address_type = "IPV4"
  enabled         = true

  attributes {
    flow_logs_enabled   = true
    flow_logs_s3_bucket = "sample"
    flow_logs_s3_prefix = "globalaccelerator/"
  }
}

resource "aws_globalaccelerator_listener" "sample_listener_443" {
  provider        = aws.oregon
  accelerator_arn = aws_globalaccelerator_accelerator.sample_accelerator.id
  client_affinity = "NONE"
  protocol        = "TCP"

  port_range {
    from_port = 443
    to_port   = 443
  }
}

resource "aws_globalaccelerator_endpoint_group" "sample_endpoint_group_443" {
  provider                      = aws.oregon
  endpoint_group_region         = "ap-northeast-1"
  health_check_interval_seconds = 30
  health_check_path             = "/"
  health_check_protocol         = "HTTPS"
  listener_arn                  = aws_globalaccelerator_listener.sample_listener_443.id
  threshold_count               = 3
  traffic_dial_percentage       = 100

  endpoint_configuration {
    endpoint_id                    = data.aws_lb.sample.arn
    weight                         = 128
    client_ip_preservation_enabled = true
  }
}

resource "aws_globalaccelerator_listener" "sample_listener_80" {
  provider        = aws.oregon
  accelerator_arn = aws_globalaccelerator_accelerator.sample_accelerator.id
  client_affinity = "NONE"
  protocol        = "TCP"

  port_range {
    from_port = 80
    to_port   = 80
  }
}

resource "aws_globalaccelerator_endpoint_group" "sample_endpoint_group_80" {
  provider                      = aws.oregon
  endpoint_group_region         = "ap-northeast-1"
  health_check_interval_seconds = 30
  health_check_path             = "/"
  health_check_protocol         = "HTTP"
  listener_arn                  = aws_globalaccelerator_listener.sample_listener_80.id
  threshold_count               = 3
  traffic_dial_percentage       = 100

  endpoint_configuration {
    endpoint_id                    = data.aws_lb.sample.arn
    weight                         = 128
    client_ip_preservation_enabled = true
  }
}
```

```security_group.tf
// ENIにアタッチするSG
resource "aws_security_group" "sample" {
  vpc_id      = data.aws_vpc.sample.id
  name        = "sample"
  description = "sample inbound traffic"

  dynamic "ingress" {
    for_each = var.ingress_elb_ports

    content {
      from_port = ingress.value
      to_port   = ingress.value
      protocol  = "tcp"
      cidr_blocks = [
        "xxx.xxx.xxx.xxx/xx",
      ]
    }
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_security_group" "sample_elb" {
  vpc_id      = data.aws_vpc.sample.id
  name        = "sample-elb"
  description = "sample-elb inbound traffic"

  dynamic "ingress" {
    for_each = var.ingress_elb_ports

    content {
      from_port = ingress.value
      to_port   = ingress.value
      protocol  = "tcp"
      security_groups = [aws_security_group.sample.id]
    }
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
```

- 作成したSecurityGroupをNetworkInterfacesにアタッチします（NetworkInterfacesはImportしてもいいかも）
![スクリーンショット 2021-07-30 12.58.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58788/0a1cc312-b8c6-1166-d0b9-f31910c74fa0.png)

# 参考
[Best practices for client IP address preservation](https://docs.aws.amazon.com/global-accelerator/latest/dg/best-practices-aga.html)