Snippets de código en Terraform para gestionar una "Prefix List" de AWS y compartirla usando el Resource Access Manager.

Desde junio de 2020, además de las listas propias de Amazon Web Services, es posible crear tus propias Prefix List y compartirlas usando el servicio Resource Access Manager.

Una Prefix List de AWS es básicamente una lista de CIDR's con su descripción correspondiente. Estas listas se pueden asociar a un security group y autorizar el acceso de un puerto determinado a todas las IPs del listado en cuestión.

Además mediante el servicio de Amazon Web Services, Resource Access Manager, puedes compartir esa lista con otras cuentas y asociarla a los security groups creados en esas otras cuentas.

El único contra que puedo verle son los límites, pero son límites de los cuáles se puede pedir una ampliación. Cuando fijas el tamaño de una lista, tienes que tener en cuenta que ese será el tamaño de las reglas que uses cuando la autorices en un grupo de seguridad. Un grupo de seguridad con una lista de tamaño n asociada a un grupo de seguridad determinado con un límite de reglas x, tendrá ocupadas n reglas del tamaño total.

En el siguiente código de Terraform lo que hago es definir mediante un provider de AWS como alias, y según el profile, las diferentes cuentas dónde quiero compartir la lista.

                        
provider "aws" {
  alias = "account-a"
  region  = AWS_REGION
  profile = "account-a-profile"
}

provider "aws" {
  alias = "account-b"
  region  = AWS_REGION
  profile = "account-b-profile"
}
                        
                    

A continuación defino la lista en cuestión.

                        
resource "aws_ec2_managed_prefix_list" "example-test" {
  name           = "All VPC CIDR-s"
  address_family = "IPv4"
  max_entries    = 5

  entry {
    cidr        = "1.1.1.1/32"
    description = "Cidr Example 1"
  }

  entry {
    cidr        = "1.1.1.2/32"
    description = "Cidr Example 2"
  }
}
                        
                    

En el siguiente código defino toda la parte que hace referencia al Resource Access Manager, con la configuración de las diferentes cuentas con las que quiero compartir la lista.

                        
resource "aws_ram_resource_share" "cidr-list" {
  name                      = "cidr-list"
  allow_external_principals = true

  permission_arns = [
    "arn:aws:ram::aws:permission/AWSRAMDefaultPermissionPrefixList"
  ]
}

resource "aws_ram_resource_association" "cidr-list-pl" {
  resource_arn       = "arn:aws:ec2:AWS_REGION:MAIN_ACCOUNT_ID:prefix-list/${aws_ec2_managed_prefix_list.example-test.id}"
  resource_share_arn = aws_ram_resource_share.cidr-list.arn
}

resource "aws_ram_principal_association" "cidr-list-assoc-account-a" {
  principal          = ACCOUNT_A_ID
  resource_share_arn = aws_ram_resource_share.cidr-list.arn
}

resource "aws_ram_principal_association" "cidr-list-assoc-account-b" {
  principal          = ACCOUNT_B_ID
  resource_share_arn = aws_ram_resource_share.cidr-list.arn
}
                        
                    

Finalmente creo un security group de ejemplo en cada una de las cuentas asociando la lista que he compartido y autorizando el puerto 443.

                        
resource "aws_security_group" "https-account-a" {
  provider    = aws.account-a
  name        = "account-a-example"
  description = "account-a-example"
  vpc_id      = VPC_ID_A
  revoke_rules_on_delete = false

  ingress {
    protocol    = "tcp"
    from_port   = 443
    to_port     = 443
    prefix_list_ids = [aws_ec2_managed_prefix_list.example-test.id]
    description = "main account prefix-list"
  }

  egress {
    from_port = 0
    to_port   = 0
    protocol  = "-1"

    cidr_blocks = [
      "0.0.0.0/0"
    ]
  }
}

resource "aws_security_group" "https-account-b" {
  provider    = aws.account-b
  name        = "account-b-example"
  description = "account-b-example"
  vpc_id      = VPC_ID_B
  revoke_rules_on_delete = false

  ingress {
    protocol    = "tcp"
    from_port   = 443
    to_port     = 443
    prefix_list_ids = [aws_ec2_managed_prefix_list.example-test.id]
    description = "main account prefix-list"
  }

  egress {
    from_port = 0
    to_port   = 0
    protocol  = "-1"

    cidr_blocks = [
      "0.0.0.0/0"
    ]
  }
}
                        
                    

En la documentación de AWS podrás encontrar información detallada sobre Prefix Lists.