Escaneando IaC en búsqueda de Vulnerabilidades con Terrascan

Escaneando IaC en búsqueda de Vulnerabilidades con Terrascan

Escaneo de IoC con terrascan. Revisar la infraestructura como codigo no es un dolor de cabeza

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, llamada 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) 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. 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.

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.

 ~/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.

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.

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.

access_key = "XXXXX"
secret_key = "XXXXX"

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

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

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

$ 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.

¡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.