feat: multi-site scalability, locals refactor, README
This commit is contained in:
@@ -25,9 +25,8 @@ y deben aplicarse directamente en el Meraki Dashboard.
|
||||
|
||||
## OWE (Opportunistic Wireless Encryption) — SSID EQT-CORPO
|
||||
|
||||
> **Note:** This is not a provider limitation. The provider manages `auth_mode = "open-enhanced"` correctly.
|
||||
|
||||
**Dashboard:** Wireless → SSIDs → EQT-CORPO → Edit settings → Security
|
||||
|
||||
Activar manualmente **"Opportunistic Wireless Encryption"**.
|
||||
|
||||
> Terraform gestiona `auth_mode = "open-enhanced"` correctamente, pero la
|
||||
> activación inicial de OWE puede requerir confirmación manual en el Dashboard.
|
||||
After the first `terraform apply`, verify that **"Opportunistic Wireless Encryption"** is active in the Dashboard. In some cases Meraki requires a one-time manual confirmation click to enable OWE on a new SSID, even though Terraform has already pushed the correct configuration.
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
# Configuración de puertos LAN del firewall MX
|
||||
# port_id: número del puerto físico en el MX
|
||||
# type: "trunk" o "access"
|
||||
# vlan: VLAN nativa (untagged) en trunk, o VLAN de acceso en access
|
||||
appliance_ports = [
|
||||
{
|
||||
# Puerto 7: trunk hacia el stack de switches
|
||||
# VLAN nativa 109 (MANAGEMENT), permite todas las VLANs
|
||||
port_id = "7"
|
||||
enabled = true
|
||||
type = "trunk"
|
||||
vlan = 109 # MANAGEMENT - VLAN nativa (untagged)
|
||||
allowed_vlans = "all"
|
||||
},
|
||||
]
|
||||
@@ -0,0 +1,13 @@
|
||||
locals {
|
||||
appliance_ports = [
|
||||
{
|
||||
# Port 7: trunk toward the switch stack
|
||||
# Native VLAN 109 (MANAGEMENT), allows all VLANs
|
||||
port_id = "7"
|
||||
enabled = true
|
||||
type = "trunk"
|
||||
vlan = 109 # MANAGEMENT — native (untagged) VLAN
|
||||
allowed_vlans = "all"
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
# Reglas de firewall L3
|
||||
firewall_rules = [
|
||||
{
|
||||
# Permite que los switches (VLAN MANAGEMENT) lleguen a internet para acceder al Dashboard de Meraki
|
||||
comment = "Permitir MANAGEMENT a internet (acceso Dashboard Meraki)"
|
||||
policy = "allow"
|
||||
protocol = "any"
|
||||
src_cidr = "10.2.55.0/24" # VLAN 109 - MANAGEMENT
|
||||
src_port = "any"
|
||||
dest_cidr = "any"
|
||||
dest_port = "any"
|
||||
syslog_enabled = false
|
||||
},
|
||||
{
|
||||
# Permite que los APs (VLAN APs) lleguen a internet para acceder al Dashboard de Meraki
|
||||
comment = "Permitir APs a internet (acceso Dashboard Meraki)"
|
||||
policy = "allow"
|
||||
protocol = "any"
|
||||
src_cidr = "10.2.54.0/24" # VLAN 108 - APs
|
||||
src_port = "any"
|
||||
dest_cidr = "any"
|
||||
dest_port = "any"
|
||||
syslog_enabled = false
|
||||
},
|
||||
{
|
||||
# Permite que los clientes GUEST (VLAN GUEST) lleguen a internet
|
||||
comment = "Permitir GUEST a internet"
|
||||
policy = "allow"
|
||||
protocol = "any"
|
||||
src_cidr = "10.2.40.0/21" # VLAN 101 - GUEST
|
||||
src_port = "any"
|
||||
dest_cidr = "any"
|
||||
dest_port = "any"
|
||||
syslog_enabled = false
|
||||
},
|
||||
{
|
||||
# Permite que los clientes SERVERS (VLAN SERVERS) lleguen a internet
|
||||
comment = "Permitir SERVERS a internet"
|
||||
policy = "allow"
|
||||
protocol = "any"
|
||||
src_cidr = "10.2.56.0/24" # VLAN 102 - SERVERS
|
||||
src_port = "any"
|
||||
dest_cidr = "any"
|
||||
dest_port = "any"
|
||||
syslog_enabled = false
|
||||
},
|
||||
{
|
||||
# Permite que los clientes GUEST a SERVERS, TEMPORAL
|
||||
comment = "Permitir GUEST a SERVERS"
|
||||
policy = "allow"
|
||||
protocol = "any"
|
||||
src_cidr = "10.2.40.0/21" # VLAN 101 - GUEST
|
||||
src_port = "any"
|
||||
dest_cidr = "10.2.56.0/24" # VLAN 102 - SERVERS
|
||||
dest_port = "any"
|
||||
syslog_enabled = false
|
||||
},
|
||||
{
|
||||
comment = "Denegar el resto del trafico de salida"
|
||||
policy = "deny"
|
||||
protocol = "any"
|
||||
src_cidr = "any"
|
||||
src_port = "any"
|
||||
dest_cidr = "any"
|
||||
dest_port = "any"
|
||||
syslog_enabled = false
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,46 @@
|
||||
locals {
|
||||
firewall_rules = [
|
||||
{
|
||||
comment = "Allow MANAGEMENT to internet (Meraki Dashboard access)"
|
||||
policy = "allow"
|
||||
protocol = "any"
|
||||
src_cidr = "10.2.55.0/24" # VLAN 109 - MANAGEMENT
|
||||
dest_cidr = "any"
|
||||
},
|
||||
{
|
||||
comment = "Allow APs to internet (Meraki Dashboard access)"
|
||||
policy = "allow"
|
||||
protocol = "any"
|
||||
src_cidr = "10.2.54.0/24" # VLAN 108 - APs
|
||||
dest_cidr = "any"
|
||||
},
|
||||
{
|
||||
comment = "Allow GUEST to internet"
|
||||
policy = "allow"
|
||||
protocol = "any"
|
||||
src_cidr = "10.2.40.0/21" # VLAN 101 - GUEST
|
||||
dest_cidr = "any"
|
||||
},
|
||||
{
|
||||
comment = "Allow SERVERS to internet"
|
||||
policy = "allow"
|
||||
protocol = "any"
|
||||
src_cidr = "10.2.56.0/24" # VLAN 110 - SERVERS
|
||||
dest_cidr = "any"
|
||||
},
|
||||
{
|
||||
comment = "Allow GUEST to SERVERS (temporary)"
|
||||
policy = "allow"
|
||||
protocol = "any"
|
||||
src_cidr = "10.2.40.0/21" # VLAN 101 - GUEST
|
||||
dest_cidr = "10.2.56.0/24" # VLAN 110 - SERVERS
|
||||
},
|
||||
{
|
||||
comment = "Deny all other outbound traffic"
|
||||
policy = "deny"
|
||||
protocol = "any"
|
||||
src_cidr = "any"
|
||||
dest_cidr = "any"
|
||||
},
|
||||
]
|
||||
}
|
||||
+22
-32
@@ -1,42 +1,32 @@
|
||||
# Configuración de Terraform y Provider
|
||||
terraform {
|
||||
required_version = ">= 1.5.0"
|
||||
required_providers {
|
||||
meraki = {
|
||||
source = "CiscoDevNet/meraki"
|
||||
version = "1.9.0"
|
||||
}
|
||||
}
|
||||
|
||||
backend "s3" {
|
||||
bucket = "eqt-terraform-state-629066559706-us-east-1-an"
|
||||
key = "BCN01-LAB/terraform.tfstate"
|
||||
region = "us-east-1"
|
||||
dynamodb_table = "terraform-locks"
|
||||
encrypt = true
|
||||
}
|
||||
backend "s3" {} # Config injected via -backend-config in CI (see backend.hcl at repo root)
|
||||
# required_version and required_providers are declared once in modules/meraki-site/main.tf
|
||||
}
|
||||
|
||||
provider "meraki" {}
|
||||
|
||||
# Llamada al módulo meraki-site
|
||||
locals {
|
||||
organization_name = "Adevinta Information Services SLU"
|
||||
network_name = "BCN01-LAB"
|
||||
}
|
||||
|
||||
module "bcn01_lab" {
|
||||
source = "../../modules/meraki-site"
|
||||
|
||||
organization_name = var.organization_name
|
||||
network_name = var.network_name
|
||||
switch_vlans = var.switch_vlans
|
||||
firewall_rules = var.firewall_rules
|
||||
wireless_ssids = var.wireless_ssids
|
||||
radius_secret = var.radius_secret
|
||||
switch_access_policies = var.switch_access_policies
|
||||
switch_port_configs = var.switch_port_configs
|
||||
switch_stack_port_configs = var.switch_stack_port_configs
|
||||
switch_named_port_configs = var.switch_named_port_configs
|
||||
switch_management_vlan = var.switch_management_vlan
|
||||
stack_routing_interfaces = var.stack_routing_interfaces
|
||||
appliance_ports = var.appliance_ports
|
||||
mx_wan_uplinks = var.mx_wan_uplinks
|
||||
mx_warm_spare = var.mx_warm_spare
|
||||
organization_name = local.organization_name
|
||||
network_name = local.network_name
|
||||
switch_vlans = local.switch_vlans
|
||||
firewall_rules = local.firewall_rules
|
||||
wireless_ssids = local.wireless_ssids
|
||||
radius_secret = var.radius_secret
|
||||
wifi_password_psk = var.wifi_password_psk
|
||||
switch_access_policies = local.switch_access_policies
|
||||
switch_port_configs = local.switch_port_configs
|
||||
switch_stack_port_configs = local.switch_stack_port_configs
|
||||
switch_named_port_configs = local.switch_named_port_configs
|
||||
switch_management_vlan = local.switch_management_vlan
|
||||
stack_routing_interfaces = local.stack_routing_interfaces
|
||||
appliance_ports = local.appliance_ports
|
||||
mx_wan_uplinks = local.mx_wan_uplinks
|
||||
mx_warm_spare = local.mx_warm_spare
|
||||
}
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
# SSIDs wireless - BCN01
|
||||
# NOTA: El shared secret de RADIUS NO está aquí.
|
||||
# Se pasa como variable de entorno TF_VAR_radius_secret (GitHub secret: RADIUS_SECRET)
|
||||
|
||||
wireless_ssids = [
|
||||
{
|
||||
number = 0
|
||||
name = "EQT-CORPO"
|
||||
enabled = true
|
||||
auth_mode = "open-enhanced" # OWE (Opportunistic Wireless Encryption)
|
||||
# Meraki API utiliza "open-enhanced" para indicar Enhanced Open / OWE.
|
||||
# Este valor refleja exactamente lo que está configurado en el Dashboard.
|
||||
wpa_encryption_mode = "WPA3 only"
|
||||
splash_page = "Password-protected with custom RADIUS"
|
||||
ip_assignment_mode = "Bridge mode"
|
||||
use_vlan_tagging = true
|
||||
default_vlan_id = 100
|
||||
redirect_url = "https://www.adevinta.com"
|
||||
radius_servers = [
|
||||
{
|
||||
host = "15.15.15.15"
|
||||
port = 1912
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
number = 2
|
||||
name = "EQT-CORPO-OWE-OK"
|
||||
enabled = true
|
||||
visible = false # SSID oculto — no hace broadcast del nombre
|
||||
auth_mode = "open"
|
||||
wpa_encryption_mode = null # open no admite wpa_encryption_mode
|
||||
splash_page = "Password-protected with custom RADIUS"
|
||||
ip_assignment_mode = "Bridge mode"
|
||||
use_vlan_tagging = true
|
||||
default_vlan_id = 100
|
||||
redirect_url = "https://www.adevinta.com"
|
||||
radius_servers = [
|
||||
{
|
||||
host = "15.15.15.15"
|
||||
port = 1912
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
number = 1
|
||||
name = "EQT-GUEST"
|
||||
enabled = true
|
||||
auth_mode = "psk" # Modo para contraseña compartida
|
||||
encryption_mode = "wpa" # Requerido por la API Meraki para PSK
|
||||
wpa_encryption_mode = "WPA3 Transition Mode"
|
||||
# psk se inyecta via TF_VAR_wifi_password_psk (GitHub secret WIFI_PASSWORD_PSK)
|
||||
ip_assignment_mode = "Bridge mode"
|
||||
use_vlan_tagging = true
|
||||
default_vlan_id = 101
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,46 @@
|
||||
locals {
|
||||
wireless_ssids = [
|
||||
{
|
||||
number = 0
|
||||
name = "EQT-CORPO"
|
||||
enabled = true
|
||||
auth_mode = "open-enhanced" # OWE (Opportunistic Wireless Encryption)
|
||||
wpa_encryption_mode = "WPA3 only"
|
||||
splash_page = "Password-protected with custom RADIUS"
|
||||
ip_assignment_mode = "Bridge mode"
|
||||
use_vlan_tagging = true
|
||||
default_vlan_id = 100
|
||||
redirect_url = "https://www.adevinta.com"
|
||||
radius_servers = [
|
||||
{ host = "15.15.15.15", port = 1912 }
|
||||
]
|
||||
},
|
||||
{
|
||||
number = 2
|
||||
name = "EQT-CORPO-OWE-OK"
|
||||
enabled = true
|
||||
visible = false # Hidden SSID — no broadcast
|
||||
auth_mode = "open"
|
||||
splash_page = "Password-protected with custom RADIUS"
|
||||
ip_assignment_mode = "Bridge mode"
|
||||
use_vlan_tagging = true
|
||||
default_vlan_id = 100
|
||||
redirect_url = "https://www.adevinta.com"
|
||||
radius_servers = [
|
||||
{ host = "15.15.15.15", port = 1912 }
|
||||
]
|
||||
},
|
||||
{
|
||||
number = 1
|
||||
name = "EQT-GUEST"
|
||||
enabled = true
|
||||
auth_mode = "psk"
|
||||
encryption_mode = "wpa"
|
||||
wpa_encryption_mode = "WPA3 Transition Mode"
|
||||
# Password injected via TF_VAR_wifi_password_psk (GitHub Secret: WIFI_PASSWORD_PSK)
|
||||
ip_assignment_mode = "Bridge mode"
|
||||
use_vlan_tagging = true
|
||||
default_vlan_id = 101
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -1,210 +0,0 @@
|
||||
# Configuración de switches MS - BCN01-LAB
|
||||
# El shared secret de RADIUS se pasa via TF_VAR_radius_secret (GitHub secret: RADIUS_SECRET)
|
||||
|
||||
# --- POLÍTICAS DE ACCESO 802.1X ---
|
||||
switch_access_policies = [
|
||||
{
|
||||
name = "DOT1X-CORPO"
|
||||
access_policy_type = "Hybrid authentication"
|
||||
host_mode = "Multi-Auth"
|
||||
radius_accounting_enabled = false
|
||||
radius_re_authentication_interval = 0
|
||||
url_redirect_walled_garden_enabled = false
|
||||
|
||||
# VLAN a la que cae el puerto si el RADIUS no responde
|
||||
radius_failed_auth_vlan_id = 101 # GUEST
|
||||
|
||||
radius_servers = [
|
||||
{
|
||||
host = "15.15.15.15"
|
||||
port = 1912
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
# --- PUERTOS DE SWITCH ---
|
||||
# El serial aparece en Dashboard > Switches > nombre del switch > Overview.
|
||||
# access_policy_number: número auto-asignado por Meraki a la política creada arriba
|
||||
# (visible en Dashboard > Switches > Switch settings > Access policies)
|
||||
#
|
||||
# Ejemplo con los tres tipos de puerto:
|
||||
# switch_port_configs = [
|
||||
#
|
||||
# # Puertos de acceso general con 802.1X (PCs, portátiles)
|
||||
# # Autenticación: 802.1X → MAB → VLAN GUEST si falla RADIUS
|
||||
# # La VLAN final la asigna Okta dinámicamente; vlan=100 es el fallback estático
|
||||
# {
|
||||
# serial = "XXXX-XXXX-XXXX"
|
||||
# port_range = "1-20"
|
||||
# type = "access"
|
||||
# vlan = 100 # ACCESS - fallback si Okta no devuelve VLAN
|
||||
# access_policy_type = "Custom access policy"
|
||||
# access_policy_number = 1 # id de la política DOT1X-CORPO
|
||||
# },
|
||||
#
|
||||
# # Puertos designados para impresoras (sin 802.1X)
|
||||
# # VLAN asignada estáticamente en el puerto - las Group Policies en switches no asignan VLAN
|
||||
# {
|
||||
# serial = "XXXX-XXXX-XXXX"
|
||||
# port_range = "21-24"
|
||||
# type = "access"
|
||||
# vlan = 103 # PRINTERS - VLAN fija en el puerto
|
||||
# access_policy_type = "Open"
|
||||
# },
|
||||
#
|
||||
# # Puertos designados para APs (sin 802.1X)
|
||||
# # Igual que impresoras: VLAN fija en el puerto
|
||||
# {
|
||||
# serial = "XXXX-XXXX-XXXX"
|
||||
# port_range = "25-27"
|
||||
# type = "access"
|
||||
# vlan = 108 # APs - VLAN fija en el puerto
|
||||
# access_policy_type = "Open"
|
||||
# },
|
||||
#
|
||||
# # Puerto de uplink (trunk, sin autenticación)
|
||||
# {
|
||||
# serial = "XXXX-XXXX-XXXX"
|
||||
# port_range = "28"
|
||||
# type = "trunk"
|
||||
# access_policy_type = "Open"
|
||||
# },
|
||||
#
|
||||
# ]
|
||||
switch_port_configs = []
|
||||
|
||||
# --- PUERTOS DE STACK ---
|
||||
# Terraform resuelve automáticamente los seriales de todos los miembros del stack.
|
||||
# El stack_name debe coincidir exactamente con el nombre en Dashboard > Switches > Stacks.
|
||||
# Terraform aplicará el mismo port_range a CADA switch del stack (ambos de 48 puertos).
|
||||
#
|
||||
# Ejemplo para bnc01-lab-stack01 (2x 48 puertos):
|
||||
# switch_stack_port_configs = [
|
||||
#
|
||||
# # Puertos 1-44: acceso general con 802.1X (PCs, portátiles)
|
||||
# {
|
||||
# stack_name = "bnc01-lab-stack01"
|
||||
# port_range = "1-44"
|
||||
# type = "access"
|
||||
# vlan = 100 # ACCESS - fallback si Okta no devuelve VLAN
|
||||
# access_policy_type = "Custom access policy"
|
||||
# access_policy_number = 1 # id de la política DOT1X-CORPO
|
||||
# },
|
||||
#
|
||||
# # Puertos 45-46: impresoras (VLAN fija, sin 802.1X)
|
||||
# {
|
||||
# stack_name = "bnc01-lab-stack01"
|
||||
# port_range = "45-46"
|
||||
# type = "access"
|
||||
# vlan = 103 # PRINTERS
|
||||
# access_policy_type = "Open"
|
||||
# },
|
||||
#
|
||||
# # Puertos 47-48: APs (VLAN fija, sin 802.1X)
|
||||
# {
|
||||
# stack_name = "bnc01-lab-stack01"
|
||||
# port_range = "47-48"
|
||||
# type = "access"
|
||||
# vlan = 108 # APs
|
||||
# access_policy_type = "Open"
|
||||
# },
|
||||
#
|
||||
# ]
|
||||
switch_stack_port_configs = [
|
||||
{
|
||||
stack_name = "bcn01-lab-stack01"
|
||||
port_range = "6"
|
||||
type = "access"
|
||||
vlan = 101 # GUEST
|
||||
access_policy_type = "Open"
|
||||
},
|
||||
{
|
||||
# Puerto 44: ISP router (acceso WAN)
|
||||
stack_name = "bcn01-lab-stack01"
|
||||
port_range = "44"
|
||||
name = "ISP router 1"
|
||||
type = "access"
|
||||
vlan = 111 # WAN
|
||||
access_policy_type = "Open"
|
||||
},
|
||||
{
|
||||
# Puerto 45: WAN1 del MX primary
|
||||
stack_name = "bcn01-lab-stack01"
|
||||
port_range = "45"
|
||||
name = "WAN 1 BCN01-F04-MX01"
|
||||
type = "access"
|
||||
vlan = 111 # WAN
|
||||
access_policy_type = "Open"
|
||||
},
|
||||
{
|
||||
# Puerto 46: WAN1 del MX spare
|
||||
stack_name = "bcn01-lab-stack01"
|
||||
port_range = "46"
|
||||
name = "WAN 1 BCN01-F04-MX02"
|
||||
type = "access"
|
||||
vlan = 111 # WAN
|
||||
access_policy_type = "Open"
|
||||
},
|
||||
{
|
||||
# Puerto 47: uplink LAN del MX primary
|
||||
stack_name = "bcn01-lab-stack01"
|
||||
port_range = "47"
|
||||
name = "UPLINK LAN BCN01-F04-MX01"
|
||||
type = "trunk"
|
||||
vlan = 109 # MANAGEMENT - VLAN nativa (untagged)
|
||||
allowed_vlans = "all"
|
||||
access_policy_type = "Open"
|
||||
},
|
||||
{
|
||||
# Puerto 48: uplink LAN del MX spare
|
||||
stack_name = "bcn01-lab-stack01"
|
||||
port_range = "48"
|
||||
name = "UPLINK LAN BCN01-F04-MX02"
|
||||
type = "trunk"
|
||||
vlan = 109 # MANAGEMENT - VLAN nativa (untagged)
|
||||
allowed_vlans = "all"
|
||||
access_policy_type = "Open"
|
||||
},
|
||||
]
|
||||
|
||||
# Puertos de un switch concreto (miembro individual del stack)
|
||||
# El serial se encuentra en: Dashboard > Switches > eqt-lab-st01-sw01 > Overview
|
||||
switch_named_port_configs = [
|
||||
{
|
||||
# Puerto 1 de eqt-lab-st01-sw01 → VLAN SERVERS (estática, sin autenticación)
|
||||
switch_name = "eqt-lab-st01-sw01"
|
||||
port_range = "1"
|
||||
name = "Servers"
|
||||
type = "access"
|
||||
vlan = 101 # SERVERS
|
||||
access_policy_type = "Open"
|
||||
},
|
||||
{
|
||||
# Puertos 2 y 3 de eqt-lab-st01-sw01 → APs (trunk, nativa 108 APs, tageadas 100 ACCESS y 101 GUEST)
|
||||
switch_name = "eqt-lab-st01-sw01"
|
||||
port_range = "2,3"
|
||||
name = "AP"
|
||||
type = "trunk"
|
||||
vlan = 108 # APs - VLAN nativa (untagged)
|
||||
allowed_vlans = "100,101,108" # ACCESS + GUEST + APs
|
||||
access_policy_type = "Open"
|
||||
},
|
||||
]
|
||||
|
||||
# VLAN de gestión de los switches del site
|
||||
switch_management_vlan = 109
|
||||
|
||||
# Interfaces L3 en el stack para acceso de gestión al Dashboard de Meraki
|
||||
stack_routing_interfaces = [
|
||||
{
|
||||
stack_name = "bcn01-lab-stack01"
|
||||
name = "MANAGEMENT"
|
||||
vlan_id = 109
|
||||
ip_address = "10.2.55.2"
|
||||
subnet = "10.2.55.0/24"
|
||||
default_gateway = "10.2.55.1"
|
||||
dns1 = "8.8.8.8"
|
||||
dns2 = "8.8.4.4"
|
||||
},
|
||||
]
|
||||
@@ -0,0 +1,121 @@
|
||||
locals {
|
||||
# 802.1X access policies
|
||||
# The RADIUS shared secret is injected from var.radius_secret — never put it here.
|
||||
switch_access_policies = [
|
||||
{
|
||||
name = "DOT1X-CORPO"
|
||||
access_policy_type = "Hybrid authentication"
|
||||
host_mode = "Multi-Auth"
|
||||
radius_accounting_enabled = false
|
||||
radius_re_authentication_interval = 0
|
||||
url_redirect_walled_garden_enabled = false
|
||||
radius_failed_auth_vlan_id = 101 # Fallback to GUEST if RADIUS unreachable
|
||||
radius_servers = [
|
||||
{ host = "15.15.15.15", port = 1912 }
|
||||
]
|
||||
},
|
||||
]
|
||||
|
||||
# Ports by explicit serial — use when targeting a switch directly by serial number
|
||||
# Example:
|
||||
# switch_port_configs = [
|
||||
# {
|
||||
# serial = "XXXX-XXXX-XXXX"
|
||||
# port_range = "1-20"
|
||||
# type = "access"
|
||||
# vlan = 100 # ACCESS — fallback if RADIUS doesn't assign a VLAN
|
||||
# access_policy_type = "Custom access policy"
|
||||
# access_policy_number = 1 # references DOT1X-CORPO above
|
||||
# },
|
||||
# ]
|
||||
switch_port_configs = []
|
||||
|
||||
# Ports by stack name — Terraform resolves serials for all stack members automatically.
|
||||
# The same port_range is applied to EVERY switch in the stack.
|
||||
switch_stack_port_configs = [
|
||||
{
|
||||
stack_name = "bcn01-lab-stack01"
|
||||
port_range = "6"
|
||||
type = "access"
|
||||
vlan = 101 # GUEST
|
||||
access_policy_type = "Open"
|
||||
},
|
||||
{
|
||||
stack_name = "bcn01-lab-stack01"
|
||||
port_range = "44"
|
||||
name = "ISP router 1"
|
||||
type = "access"
|
||||
vlan = 111 # WAN
|
||||
access_policy_type = "Open"
|
||||
},
|
||||
{
|
||||
stack_name = "bcn01-lab-stack01"
|
||||
port_range = "45"
|
||||
name = "WAN 1 BCN01-F04-MX01"
|
||||
type = "access"
|
||||
vlan = 111 # WAN
|
||||
access_policy_type = "Open"
|
||||
},
|
||||
{
|
||||
stack_name = "bcn01-lab-stack01"
|
||||
port_range = "46"
|
||||
name = "WAN 1 BCN01-F04-MX02"
|
||||
type = "access"
|
||||
vlan = 111 # WAN
|
||||
access_policy_type = "Open"
|
||||
},
|
||||
{
|
||||
stack_name = "bcn01-lab-stack01"
|
||||
port_range = "47"
|
||||
name = "UPLINK LAN BCN01-F04-MX01"
|
||||
type = "trunk"
|
||||
vlan = 109 # MANAGEMENT — native (untagged) VLAN
|
||||
allowed_vlans = "all"
|
||||
access_policy_type = "Open"
|
||||
},
|
||||
{
|
||||
stack_name = "bcn01-lab-stack01"
|
||||
port_range = "48"
|
||||
name = "UPLINK LAN BCN01-F04-MX02"
|
||||
type = "trunk"
|
||||
vlan = 109 # MANAGEMENT — native (untagged) VLAN
|
||||
allowed_vlans = "all"
|
||||
access_policy_type = "Open"
|
||||
},
|
||||
]
|
||||
|
||||
# Ports by switch display name — targets a specific stack member without knowing its serial
|
||||
switch_named_port_configs = [
|
||||
{
|
||||
switch_name = "eqt-lab-st01-sw01"
|
||||
port_range = "1"
|
||||
name = "Servers"
|
||||
type = "access"
|
||||
vlan = 101 # SERVERS
|
||||
access_policy_type = "Open"
|
||||
},
|
||||
{
|
||||
switch_name = "eqt-lab-st01-sw01"
|
||||
port_range = "2,3"
|
||||
name = "AP"
|
||||
type = "trunk"
|
||||
vlan = 108 # APs — native (untagged) VLAN
|
||||
allowed_vlans = "100,101,108" # ACCESS + GUEST + APs
|
||||
access_policy_type = "Open"
|
||||
},
|
||||
]
|
||||
|
||||
switch_management_vlan = 109
|
||||
|
||||
# L3 routing interfaces on the stack (SVIs for management access to Meraki Dashboard)
|
||||
stack_routing_interfaces = [
|
||||
{
|
||||
stack_name = "bcn01-lab-stack01"
|
||||
name = "MANAGEMENT"
|
||||
vlan_id = 109
|
||||
ip_address = "10.2.55.2"
|
||||
subnet = "10.2.55.0/24"
|
||||
default_gateway = "10.2.55.1"
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -1,209 +1,15 @@
|
||||
# Definición de la Organización
|
||||
variable "organization_name" {
|
||||
type = string
|
||||
description = "Nombre exacto de tu organización en el Dashboard de Meraki"
|
||||
}
|
||||
# Sensitive variables — injected via TF_VAR_* environment variables (GitHub Secrets).
|
||||
# Never put values for these in any .tf file.
|
||||
|
||||
# Definición de la Red
|
||||
variable "network_name" {
|
||||
type = string
|
||||
description = "Nombre de la red (Network) donde reside el switch"
|
||||
}
|
||||
|
||||
|
||||
# Reglas de firewall L3
|
||||
variable "firewall_rules" {
|
||||
type = list(object({
|
||||
comment = string
|
||||
policy = string
|
||||
protocol = string
|
||||
src_cidr = string
|
||||
src_port = string
|
||||
dest_cidr = string
|
||||
dest_port = string
|
||||
syslog_enabled = optional(bool, false)
|
||||
}))
|
||||
default = []
|
||||
description = "Lista de reglas de firewall L3 para el site"
|
||||
}
|
||||
|
||||
# SSIDs wireless
|
||||
variable "wireless_ssids" {
|
||||
type = list(object({
|
||||
number = number
|
||||
name = string
|
||||
enabled = optional(bool, true)
|
||||
auth_mode = string
|
||||
psk = optional(string, null)
|
||||
encryption_mode = optional(string, null) # "wpa" para PSK; null para open/OWE
|
||||
splash_page = optional(string, "None")
|
||||
wpa_encryption_mode = optional(string, "WPA3 only")
|
||||
ip_assignment_mode = optional(string, "Bridge mode")
|
||||
use_vlan_tagging = optional(bool, false)
|
||||
default_vlan_id = optional(number, null)
|
||||
redirect_url = optional(string, "")
|
||||
radius_servers = optional(list(object({
|
||||
host = string
|
||||
port = number
|
||||
})), [])
|
||||
}))
|
||||
default = []
|
||||
description = "Lista de SSIDs wireless a configurar en el site"
|
||||
}
|
||||
|
||||
variable "wifi_password_psk" {
|
||||
type = string
|
||||
description = "Password para la SSID WPA2 desde GitHub Secrets"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
# Shared secret para servidores RADIUS (sensible, no incluir en tfvars)
|
||||
variable "radius_secret" {
|
||||
type = string
|
||||
sensitive = true
|
||||
default = ""
|
||||
description = "Shared secret para autenticación RADIUS. Pasar via TF_VAR_radius_secret"
|
||||
description = "RADIUS shared secret. Pass via TF_VAR_radius_secret (GitHub Secret: RADIUS_SECRET)."
|
||||
}
|
||||
|
||||
# Definición de VLANs
|
||||
variable "switch_vlans" {
|
||||
type = map(object({
|
||||
name = string
|
||||
subnet = optional(string, null)
|
||||
appliance_ip = optional(string, null)
|
||||
dhcp_handling = optional(string, "Run a DHCP server")
|
||||
reserved_ip_ranges = optional(list(object({
|
||||
comment = string
|
||||
id = string
|
||||
start = string
|
||||
end = string
|
||||
})), [])
|
||||
}))
|
||||
description = "Mapa de configuraciones de VLAN. La clave del mapa será el ID de la VLAN"
|
||||
}
|
||||
|
||||
|
||||
# Políticas de acceso 802.1X para switches
|
||||
variable "switch_access_policies" {
|
||||
type = list(object({
|
||||
name = string
|
||||
access_policy_type = optional(string, "802.1x")
|
||||
host_mode = optional(string, "Multi-Auth")
|
||||
radius_accounting_enabled = optional(bool, false)
|
||||
radius_testing_enabled = optional(bool, false)
|
||||
radius_coa_support_enabled = optional(bool, false)
|
||||
radius_failed_auth_vlan_id = optional(number, null)
|
||||
radius_re_authentication_interval = optional(number, 0)
|
||||
url_redirect_walled_garden_enabled = optional(bool, false)
|
||||
radius_servers = list(object({
|
||||
host = string
|
||||
port = number
|
||||
}))
|
||||
}))
|
||||
default = []
|
||||
description = "Políticas de acceso 802.1X para switches MS"
|
||||
}
|
||||
|
||||
# Configuración de puertos de switch
|
||||
variable "switch_port_configs" {
|
||||
type = list(object({
|
||||
serial = string
|
||||
port_range = string
|
||||
name = optional(string, "")
|
||||
type = optional(string, "access")
|
||||
vlan = optional(number, null)
|
||||
allowed_vlans = optional(string, "all")
|
||||
access_policy_type = optional(string, "Open")
|
||||
access_policy_number = optional(number, null)
|
||||
}))
|
||||
default = []
|
||||
description = "Puertos de switch a configurar con 802.1X. Requiere serial del switch."
|
||||
}
|
||||
|
||||
variable "switch_stack_port_configs" {
|
||||
type = list(object({
|
||||
stack_name = string
|
||||
port_range = string
|
||||
name = optional(string, "")
|
||||
type = optional(string, "access")
|
||||
vlan = optional(number, null)
|
||||
allowed_vlans = optional(string, "all")
|
||||
access_policy_type = optional(string, "Open")
|
||||
access_policy_number = optional(number, null)
|
||||
}))
|
||||
default = []
|
||||
description = "Puertos de stack a configurar por nombre. Terraform resuelve los seriales automáticamente."
|
||||
}
|
||||
|
||||
variable "switch_named_port_configs" {
|
||||
type = list(object({
|
||||
switch_name = string
|
||||
port_range = string
|
||||
name = optional(string, "")
|
||||
type = optional(string, "access")
|
||||
vlan = optional(number, null)
|
||||
allowed_vlans = optional(string, "all")
|
||||
access_policy_type = optional(string, "Open")
|
||||
access_policy_number = optional(number, null)
|
||||
}))
|
||||
default = []
|
||||
description = "Puertos de switch a configurar por nombre de dispositivo. Terraform resuelve el serial automáticamente."
|
||||
}
|
||||
|
||||
variable "switch_management_vlan" {
|
||||
type = number
|
||||
default = null
|
||||
description = "VLAN ID de gestión para los switches del site."
|
||||
}
|
||||
|
||||
variable "stack_routing_interfaces" {
|
||||
type = list(object({
|
||||
stack_name = string
|
||||
name = string
|
||||
vlan_id = number
|
||||
ip_address = string
|
||||
subnet = string
|
||||
default_gateway = optional(string, null)
|
||||
dns1 = optional(string, null)
|
||||
dns2 = optional(string, null)
|
||||
}))
|
||||
default = []
|
||||
description = "Interfaces L3 (SVIs) en stacks de switches para acceso de gestión al Dashboard."
|
||||
}
|
||||
|
||||
variable "appliance_ports" {
|
||||
type = list(object({
|
||||
port_id = string
|
||||
enabled = optional(bool, true)
|
||||
type = optional(string, "access")
|
||||
vlan = optional(number, null)
|
||||
allowed_vlans = optional(string, "all")
|
||||
drop_untagged_traffic = optional(bool, false)
|
||||
}))
|
||||
default = []
|
||||
description = "Configuración de puertos LAN del firewall MX."
|
||||
}
|
||||
|
||||
variable "mx_warm_spare" {
|
||||
type = object({
|
||||
enabled = optional(bool, true)
|
||||
spare_name = string
|
||||
uplink_mode = optional(string, "virtual")
|
||||
virtual_ip1 = optional(string, null)
|
||||
virtual_ip2 = optional(string, null)
|
||||
})
|
||||
default = null
|
||||
description = "Configuración Warm Spare (HA) del MX."
|
||||
}
|
||||
|
||||
variable "mx_wan_uplinks" {
|
||||
type = list(object({
|
||||
name = string # Nombre del dispositivo en el Dashboard
|
||||
wan1_static_ip = optional(string, null)
|
||||
wan1_static_subnet_mask = optional(string, null)
|
||||
wan1_static_gateway_ip = optional(string, null)
|
||||
wan1_static_dns = optional(list(string), null)
|
||||
}))
|
||||
default = []
|
||||
description = "Configuración WAN1 estática de los MX. El serial se resuelve automáticamente por nombre de dispositivo."
|
||||
variable "wifi_password_psk" {
|
||||
type = string
|
||||
sensitive = true
|
||||
description = "PSK Wi-Fi password. Pass via TF_VAR_wifi_password_psk (GitHub Secret: WIFI_PASSWORD_PSK)."
|
||||
}
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
# Nombre exacto que aparece en tu Dashboard de Meraki
|
||||
organization_name = "Adevinta Information Services SLU"
|
||||
network_name = "BCN01-LAB"
|
||||
|
||||
# Configuración de las VLANs (L3)
|
||||
# La clave (ej. "10") es el ID de la VLAN
|
||||
switch_vlans = {
|
||||
"100" = {
|
||||
name = "ACCESS"
|
||||
subnet = "10.2.32.0/21"
|
||||
appliance_ip = "10.2.32.1"
|
||||
reserved_ip_ranges = [
|
||||
{ comment = "Estáticas reservadas", id = "static", start = "10.2.32.1", end = "10.2.32.49" }
|
||||
]
|
||||
}
|
||||
"101" = {
|
||||
name = "GUEST"
|
||||
subnet = "10.2.40.0/21"
|
||||
appliance_ip = "10.2.40.1"
|
||||
reserved_ip_ranges = [
|
||||
{ comment = "Estáticas reservadas", id = "static", start = "10.2.40.1", end = "10.2.40.49" }
|
||||
]
|
||||
}
|
||||
"102" = {
|
||||
name = "VC"
|
||||
subnet = "10.2.48.0/24"
|
||||
appliance_ip = "10.2.48.1"
|
||||
reserved_ip_ranges = [
|
||||
{ comment = "Estáticas reservadas", id = "static", start = "10.2.48.1", end = "10.2.48.49" }
|
||||
]
|
||||
}
|
||||
"103" = {
|
||||
name = "PRINTERS"
|
||||
subnet = "10.2.49.0/24"
|
||||
appliance_ip = "10.2.49.1"
|
||||
reserved_ip_ranges = [
|
||||
{ comment = "Estáticas reservadas", id = "static", start = "10.2.49.1", end = "10.2.49.49" }
|
||||
]
|
||||
}
|
||||
"104" = {
|
||||
name = "DISPLAYS"
|
||||
subnet = "10.2.50.0/24"
|
||||
appliance_ip = "10.2.50.1"
|
||||
reserved_ip_ranges = [
|
||||
{ comment = "Estáticas reservadas", id = "static", start = "10.2.50.1", end = "10.2.50.49" }
|
||||
]
|
||||
}
|
||||
"105" = {
|
||||
name = "BOOKING"
|
||||
subnet = "10.2.51.0/24"
|
||||
appliance_ip = "10.2.51.1"
|
||||
reserved_ip_ranges = [
|
||||
{ comment = "Estáticas reservadas", id = "static", start = "10.2.51.1", end = "10.2.51.49" }
|
||||
]
|
||||
}
|
||||
"106" = {
|
||||
name = "BADGE_READERS"
|
||||
subnet = "10.2.52.0/24"
|
||||
appliance_ip = "10.2.52.1"
|
||||
reserved_ip_ranges = [
|
||||
{ comment = "Estáticas reservadas", id = "static", start = "10.2.52.1", end = "10.2.52.49" }
|
||||
]
|
||||
}
|
||||
"107" = {
|
||||
name = "CCTV"
|
||||
subnet = "10.2.53.0/24"
|
||||
appliance_ip = "10.2.53.1"
|
||||
reserved_ip_ranges = [
|
||||
{ comment = "Estáticas reservadas", id = "static", start = "10.2.53.1", end = "10.2.53.49" }
|
||||
]
|
||||
}
|
||||
"108" = {
|
||||
name = "APs"
|
||||
subnet = "10.2.54.0/24"
|
||||
appliance_ip = "10.2.54.1"
|
||||
reserved_ip_ranges = [
|
||||
{ comment = "Estáticas reservadas", id = "static", start = "10.2.54.1", end = "10.2.54.49" }
|
||||
]
|
||||
}
|
||||
"109" = {
|
||||
name = "MANAGEMENT"
|
||||
subnet = "10.2.55.0/24"
|
||||
appliance_ip = "10.2.55.1"
|
||||
dhcp_handling = "Do not respond to DHCP requests"
|
||||
}
|
||||
"110" = {
|
||||
name = "SERVERS"
|
||||
subnet = "10.2.56.0/24"
|
||||
appliance_ip = "10.2.56.1"
|
||||
dhcp_handling = "Do not respond to DHCP requests"
|
||||
}
|
||||
"111" = {
|
||||
name = "WAN"
|
||||
dhcp_handling = "Do not respond to DHCP requests"
|
||||
# Sin L3: sin subnet ni appliance_ip (VLAN de switching puro hacia el ISP)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
locals {
|
||||
switch_vlans = {
|
||||
"100" = {
|
||||
name = "ACCESS"
|
||||
subnet = "10.2.32.0/21"
|
||||
appliance_ip = "10.2.32.1"
|
||||
reserved_ip_ranges = [
|
||||
{ comment = "Static reserved", id = "static", start = "10.2.32.1", end = "10.2.32.49" }
|
||||
]
|
||||
}
|
||||
"101" = {
|
||||
name = "GUEST"
|
||||
subnet = "10.2.40.0/21"
|
||||
appliance_ip = "10.2.40.1"
|
||||
reserved_ip_ranges = [
|
||||
{ comment = "Static reserved", id = "static", start = "10.2.40.1", end = "10.2.40.49" }
|
||||
]
|
||||
}
|
||||
"102" = {
|
||||
name = "VC"
|
||||
subnet = "10.2.48.0/24"
|
||||
appliance_ip = "10.2.48.1"
|
||||
reserved_ip_ranges = [
|
||||
{ comment = "Static reserved", id = "static", start = "10.2.48.1", end = "10.2.48.49" }
|
||||
]
|
||||
}
|
||||
"103" = {
|
||||
name = "PRINTERS"
|
||||
subnet = "10.2.49.0/24"
|
||||
appliance_ip = "10.2.49.1"
|
||||
reserved_ip_ranges = [
|
||||
{ comment = "Static reserved", id = "static", start = "10.2.49.1", end = "10.2.49.49" }
|
||||
]
|
||||
}
|
||||
"104" = {
|
||||
name = "DISPLAYS"
|
||||
subnet = "10.2.50.0/24"
|
||||
appliance_ip = "10.2.50.1"
|
||||
reserved_ip_ranges = [
|
||||
{ comment = "Static reserved", id = "static", start = "10.2.50.1", end = "10.2.50.49" }
|
||||
]
|
||||
}
|
||||
"105" = {
|
||||
name = "BOOKING"
|
||||
subnet = "10.2.51.0/24"
|
||||
appliance_ip = "10.2.51.1"
|
||||
reserved_ip_ranges = [
|
||||
{ comment = "Static reserved", id = "static", start = "10.2.51.1", end = "10.2.51.49" }
|
||||
]
|
||||
}
|
||||
"106" = {
|
||||
name = "BADGE_READERS"
|
||||
subnet = "10.2.52.0/24"
|
||||
appliance_ip = "10.2.52.1"
|
||||
reserved_ip_ranges = [
|
||||
{ comment = "Static reserved", id = "static", start = "10.2.52.1", end = "10.2.52.49" }
|
||||
]
|
||||
}
|
||||
"107" = {
|
||||
name = "CCTV"
|
||||
subnet = "10.2.53.0/24"
|
||||
appliance_ip = "10.2.53.1"
|
||||
reserved_ip_ranges = [
|
||||
{ comment = "Static reserved", id = "static", start = "10.2.53.1", end = "10.2.53.49" }
|
||||
]
|
||||
}
|
||||
"108" = {
|
||||
name = "APs"
|
||||
subnet = "10.2.54.0/24"
|
||||
appliance_ip = "10.2.54.1"
|
||||
reserved_ip_ranges = [
|
||||
{ comment = "Static reserved", id = "static", start = "10.2.54.1", end = "10.2.54.49" }
|
||||
]
|
||||
}
|
||||
"109" = {
|
||||
name = "MANAGEMENT"
|
||||
subnet = "10.2.55.0/24"
|
||||
appliance_ip = "10.2.55.1"
|
||||
dhcp_handling = "Do not respond to DHCP requests"
|
||||
}
|
||||
"110" = {
|
||||
name = "SERVERS"
|
||||
subnet = "10.2.56.0/24"
|
||||
appliance_ip = "10.2.56.1"
|
||||
dhcp_handling = "Do not respond to DHCP requests"
|
||||
}
|
||||
"111" = {
|
||||
name = "WAN"
|
||||
dhcp_handling = "Do not respond to DHCP requests"
|
||||
# No subnet or appliance_ip — L2-only switching VLAN toward the ISP
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
# Configuración WAN1 estática de los firewalls MX
|
||||
# El nombre debe coincidir exactamente con el nombre del dispositivo en el Dashboard
|
||||
# Dashboard > Security & SD-WAN > Appliance > nombre del dispositivo
|
||||
|
||||
# Warm Spare (HA): VIP flotante entre primary y spare
|
||||
# La IP de salida del tráfico será siempre la VIP
|
||||
mx_warm_spare = {
|
||||
enabled = true
|
||||
spare_name = "BCN01-F04-MX02"
|
||||
uplink_mode = "virtual"
|
||||
virtual_ip1 = "213.229.159.148" # VIP WAN1
|
||||
virtual_ip2 = "10.212.160.40" # VIP WAN2
|
||||
}
|
||||
|
||||
mx_wan_uplinks = [
|
||||
{
|
||||
# MX Primary
|
||||
name = "BCN01-F04-MX01" # TODO: ajustar al nombre real en el Dashboard
|
||||
wan1_static_ip = "213.229.159.145"
|
||||
wan1_static_subnet_mask = "255.255.255.240" # /28
|
||||
wan1_static_gateway_ip = "213.229.159.147"
|
||||
wan1_static_dns = ["8.8.8.8", "8.8.4.4"]
|
||||
},
|
||||
{
|
||||
# MX Spare (Warm Spare / HA)
|
||||
name = "BCN01-F04-MX02" # TODO: ajustar al nombre real en el Dashboard
|
||||
wan1_static_ip = "213.229.159.146"
|
||||
wan1_static_subnet_mask = "255.255.255.240" # /28
|
||||
wan1_static_gateway_ip = "213.229.159.147"
|
||||
wan1_static_dns = ["8.8.8.8", "8.8.4.4"]
|
||||
},
|
||||
]
|
||||
@@ -0,0 +1,29 @@
|
||||
locals {
|
||||
# Warm Spare (HA) — floating VIP between primary and spare MX
|
||||
mx_warm_spare = {
|
||||
enabled = true
|
||||
spare_name = "BCN01-F04-MX02"
|
||||
uplink_mode = "virtual"
|
||||
virtual_ip1 = "213.229.159.148" # Floating VIP on WAN1
|
||||
virtual_ip2 = "10.212.160.40" # Floating VIP on WAN2
|
||||
}
|
||||
|
||||
# Static WAN1 configuration for each MX
|
||||
# Device serials are resolved automatically from the display name
|
||||
mx_wan_uplinks = [
|
||||
{
|
||||
name = "BCN01-F04-MX01"
|
||||
wan1_static_ip = "213.229.159.145"
|
||||
wan1_static_subnet_mask = "255.255.255.240" # /28
|
||||
wan1_static_gateway_ip = "213.229.159.147"
|
||||
wan1_static_dns = ["8.8.8.8", "8.8.4.4"]
|
||||
},
|
||||
{
|
||||
name = "BCN01-F04-MX02"
|
||||
wan1_static_ip = "213.229.159.146"
|
||||
wan1_static_subnet_mask = "255.255.255.240" # /28
|
||||
wan1_static_gateway_ip = "213.229.159.147"
|
||||
wan1_static_dns = ["8.8.8.8", "8.8.4.4"]
|
||||
},
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user