# Escaneando IaC en búsqueda de Vulnerabilidades con Terrascan

Si le pregunta es: ¿Podemos automatizar una infraestructura? La respuesta sera: ¡Si!. Muchas empresas estan optando por tener su Infraestructura como Código, conocida como IaC. Es por ello que nosotros, los de Seguridad, tenemos que poner ojo en ese "Template" y cuanto antes lo hagamos, mejor.

A medida que se adopta IoC, como practica, como Terraform, Kubernetes o AWS CloudFormation, es importante observar las mejores practicas de Seguridad y los requisitos de Cumplimiento. Para ello vamos a probar una herramienta, recién liberada por [Accurics](https://www.accurics.com/), llamada [Terrascan](https://github.com/accurics/terrascan) que nos proporciona más de 500 políticas listas para usar para que pueda escanear IaC frente a estándares de políticas comunes, como CIS Benchmark. Nos da la posibilidad de optar por el motor Open Policy Agent ([OPA](https://www.openpolicyagent.org/)) para crear políticas personalizadas utilizando el lenguaje de consulta Rego. Terrascan soporta AWS GCP y Azure.

Para probar vamos a utilizar nuestro primer código [Terraform](https://learn.hashicorp.com/terraform). Vamos a crear una VPC, en AWS, con sus respectivas Subredes, una privada y otra publica, Internet Gateway, NAT Gateway y Rutas.

Creamos nuestro Workspace y los archivos, de configuración, necesarios.

```bash
mkdir terraform
cd terraform/
terraform init
touch main.tf
touch variables.tf
touch terraform.tfvars
```

Nos debería quedar algo asi, luego explicaremos un poco cada fichero.

```bash
 ~/Terraform  tree                                      ok
.
├── main.tf
├── terraform.tfvars
└── variables.tf

0 directories, 3 files
```

En nuestro main.tf vamos a crear todos los recursos necesarios para darle forma a nuestra VPC.

```bash
provider "aws" {
      region     = var.region}
      access_key = {var.access_key}
      secret_key = {var.secret_key}
}


# VPC Rercursos: Vamos a crear 1 VPC con 4 Subnets, 1 Internet Gateway, 4 Rutas.

resource "aws_vpc" "default" {
  cidr_block           = var.cidr_block
  enable_dns_support   = true
  enable_dns_hostnames = true
}

resource "aws_internet_gateway" "default" {
  vpc_id = aws_vpc.default.id
}

resource "aws_route_table" "private" {
  count = length(var.private_subnet_cidr_blocks)

  vpc_id = aws_vpc.default.id
}

resource "aws_route" "private" {
  count = length(var.private_subnet_cidr_blocks)

  route_table_id         = aws_route_table.private[count.index].id
  destination_cidr_block = "0.0.0.0/0"
  nat_gateway_id         = aws_nat_gateway.default[count.index].id
}

resource "aws_route_table" "public" {
  vpc_id = aws_vpc.default.id
}

resource "aws_route" "public" {
  route_table_id         = aws_route_table.public.id
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = aws_internet_gateway.default.id
}

resource "aws_subnet" "private" {
  count = length(var.private_subnet_cidr_blocks)

  vpc_id            = aws_vpc.default.id
  cidr_block        = var.private_subnet_cidr_blocks[count.index]
  availability_zone = var.availability_zones[count.index]
}

resource "aws_subnet" "public" {
  count = length(var.public_subnet_cidr_blocks)

  vpc_id                  = aws_vpc.default.id
  cidr_block              = var.public_subnet_cidr_blocks[count.index]
  availability_zone       = var.availability_zones[count.index]
  map_public_ip_on_launch = true
}

resource "aws_route_table_association" "private" {
  count = length(var.private_subnet_cidr_blocks)

  subnet_id      = aws_subnet.private[count.index].id
  route_table_id = aws_route_table.private[count.index].id
}

resource "aws_route_table_association" "public" {
  count = length(var.public_subnet_cidr_blocks)

  subnet_id      = aws_subnet.public[count.index].id
  route_table_id = aws_route_table.public.id
}


# Recursos NAT: Esto creará 2 puertas de enlace NAT en 2 subredes públicas para 2 subredes privadas diferentes.

resource "aws_eip" "nat" {
  count = length(var.public_subnet_cidr_blocks)

  vpc = true
}

resource "aws_nat_gateway" "default" {
  depends_on = ["aws_internet_gateway.default"]

  count = length(var.public_subnet_cidr_blocks)

  allocation_id = aws_eip.nat[count.index].id
  subnet_id     = aws_subnet.public[count.index].id
}
```

Luego tenemos el archivo **variables.tf**. Revisen que son objetos tipos lista, por ello en el **main.tf** hacemos el count, para recorrerla e ir creando los recursos.

```bash
variable "access_key" {
     description = "Access key to AWS console"
     
}
variable "secret_key" {
     description = "Secret key to AWS console"
     
}

variable "region" {
  default     = "eu-east-3"
  type        = string
  description = "Region of the VPC"
}


variable "cidr_block" {
  default     = "10.0.0.0/16"
  type        = string
  description = "CIDR block for the VPC"
}

variable "public_subnet_cidr_blocks" {
  default     = ["10.0.0.0/24", "10.0.2.0/24"]
  type        = list
  description = "List of public subnet CIDR blocks"
}

variable "private_subnet_cidr_blocks" {
  default     = ["10.0.1.0/24", "10.0.3.0/24"]
  type        = list
  description = "List of private subnet CIDR blocks"
}

variable "availability_zones" {
  default     = ["eu-east-3a", "eu-east-3b"]
  type        = list
  description = "List of availability zones"
}
```

Por ultimo, las lleves del reino, en el **terraform.tfvars**.

```bash
access_key = "XXXXX"
secret_key = "XXXXX"
```

Vamos a probar a ver que nos dice, si esta todo bien con **terraform plan**.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1707410296609/c077a552-8ad4-47de-b5e0-0b93885c489b.png align="center")

Vamos aplicar la infraestructura con **terraform apply**. Esperamos unos minutos y ¡listo!

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1707410310277/9314475e-0223-45a4-908c-a170a03215b7.png align="center")

Listo la parte **DevOps**, ahora vamos a meterle un poco de **Sec**. Para ello vamos a instalar terrascan.

```bash
$ curl --location https://github.com/accurics/terrascan/releases/download/v1.0.0/terrascan_1.0.0_Darwin_x86_64.tar.gz --output terrascan.tar.gz
$ tar -xvf terrascan.tar.gz
  x CHANGELOG.md
  x LICENSE
  x README.md
x terrascan
$ install terrascan /usr/local/bin
$ terrascan
```

¡Listo! Vamos a probar nuestro IoC. Para ello ejecutamos **terrascan scan -t aws**.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1707410327643/a3a6761f-dfce-4c16-ae92-366d2a2bd1e7.png align="center")

¡Belleza! Tenemos un **Medium**. No estamos habilitando, por gastos, el VPC Flow Logs. ¿Esta bien? No. ¿Es mas barato? Si. Con esas salidas, podemos jugar para integrarlo con nuestro Jenkins. Espero que les sirva la info. Saludos.
