feat(BCN01-LAB): sync manual Dashboard changes to Terraform
- Management VLAN switches → 109 - Puerto 47 stack: trunk, native VLAN 109 - SVI stack bcn01-lab-stack01: VLAN 109, 10.2.55.2/24, GW 10.2.55.1 - MX puerto 7: trunk, native VLAN 109 - Firewall: allow MANAGEMENT → internet (primera regla) - Puerto 1 eqt-lab-st01-sw01: VLAN 110 (SERVERS)
This commit is contained in:
@@ -21,6 +21,11 @@ data "meraki_switch_stacks" "stacks" {
|
||||
network_id = local.network_id
|
||||
}
|
||||
|
||||
# Dispositivos de la red (para resolución dinámica de serial por nombre de switch)
|
||||
data "meraki_devices" "devices" {
|
||||
network_id = local.network_id
|
||||
}
|
||||
|
||||
# Local para extraer el network_id exacto de la lista de redes
|
||||
locals {
|
||||
network_id = [for n in data.meraki_networks.net.items : n.id if n.name == var.network_name][0]
|
||||
@@ -28,8 +33,8 @@ locals {
|
||||
# Helper: expande un port_range en lista de port_ids
|
||||
# "1-48" -> ["1","2",...,"48"] | "1" -> ["1"]
|
||||
_expand_range = {
|
||||
for config in concat(var.switch_port_configs, var.switch_stack_port_configs) :
|
||||
"${try(config.serial, config.stack_name)}:${config.port_range}" => (
|
||||
for config in concat(var.switch_port_configs, var.switch_stack_port_configs, var.switch_named_port_configs) :
|
||||
"${try(config.serial, try(config.stack_name, config.switch_name))}:${config.port_range}" => (
|
||||
length(split("-", config.port_range)) == 2
|
||||
? [for i in range(
|
||||
tonumber(split("-", config.port_range)[0]),
|
||||
@@ -45,6 +50,19 @@ locals {
|
||||
stack.name => stack.serials
|
||||
}
|
||||
|
||||
# Mapa de nombre de stack -> ID del stack
|
||||
stack_ids = {
|
||||
for stack in data.meraki_switch_stacks.stacks.items :
|
||||
stack.name => stack.id
|
||||
}
|
||||
|
||||
# Mapa de nombre de dispositivo -> serial
|
||||
device_serials = {
|
||||
for d in data.meraki_devices.devices.items :
|
||||
d.name => d.serial
|
||||
if d.name != null && d.name != ""
|
||||
}
|
||||
|
||||
# Expande switch_port_configs (serial explícito) en entradas individuales
|
||||
switch_ports_expanded = flatten([
|
||||
for config in var.switch_port_configs : [
|
||||
@@ -55,6 +73,7 @@ locals {
|
||||
name = config.name
|
||||
type = config.type
|
||||
vlan = config.vlan
|
||||
allowed_vlans = config.allowed_vlans
|
||||
access_policy_type = config.access_policy_type
|
||||
access_policy_number = config.access_policy_number
|
||||
}
|
||||
@@ -73,6 +92,7 @@ locals {
|
||||
name = config.name
|
||||
type = config.type
|
||||
vlan = config.vlan
|
||||
allowed_vlans = config.allowed_vlans
|
||||
access_policy_type = config.access_policy_type
|
||||
access_policy_number = config.access_policy_number
|
||||
}
|
||||
@@ -80,10 +100,28 @@ locals {
|
||||
]
|
||||
])
|
||||
|
||||
# Unión de ambas listas para el resource meraki_switch_port
|
||||
# Expande switch_named_port_configs (por nombre de switch) en entradas individuales
|
||||
named_ports_expanded = flatten([
|
||||
for config in var.switch_named_port_configs : [
|
||||
for port_id in local._expand_range["${config.switch_name}:${config.port_range}"] : {
|
||||
key = "${local.device_serials[config.switch_name]}:${port_id}"
|
||||
serial = local.device_serials[config.switch_name]
|
||||
port_id = port_id
|
||||
name = config.name
|
||||
type = config.type
|
||||
vlan = config.vlan
|
||||
allowed_vlans = config.allowed_vlans
|
||||
access_policy_type = config.access_policy_type
|
||||
access_policy_number = config.access_policy_number
|
||||
}
|
||||
]
|
||||
])
|
||||
|
||||
# Unión de todas las listas para el resource meraki_switch_port
|
||||
all_ports = merge(
|
||||
{ for p in local.switch_ports_expanded : p.key => p },
|
||||
{ for p in local.stack_ports_expanded : p.key => p }
|
||||
{ for p in local.stack_ports_expanded : p.key => p },
|
||||
{ for p in local.named_ports_expanded : p.key => p }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -176,7 +214,48 @@ resource "meraki_switch_port" "ports" {
|
||||
type = each.value.type
|
||||
|
||||
vlan = each.value.vlan
|
||||
allowed_vlans = each.value.type == "trunk" ? each.value.allowed_vlans : null
|
||||
|
||||
access_policy_type = each.value.access_policy_type
|
||||
access_policy_number = each.value.access_policy_number
|
||||
}
|
||||
|
||||
# 7. VLAN de gestión de los switches del site
|
||||
resource "meraki_networks_switch_settings" "mgmt_vlan" {
|
||||
count = var.switch_management_vlan != null ? 1 : 0
|
||||
network_id = local.network_id
|
||||
|
||||
management_vlan = var.switch_management_vlan
|
||||
}
|
||||
|
||||
# 8. Interfaces de enrutamiento L3 en stacks (SVIs para acceso de gestión al Dashboard)
|
||||
resource "meraki_networks_switch_stacks_routing_interfaces" "stack_interfaces" {
|
||||
for_each = {
|
||||
for i in var.stack_routing_interfaces :
|
||||
"${i.stack_name}:${i.vlan_id}" => i
|
||||
}
|
||||
|
||||
network_id = local.network_id
|
||||
switch_stack_id = local.stack_ids[each.value.stack_name]
|
||||
|
||||
name = each.value.name
|
||||
vlan_id = each.value.vlan_id
|
||||
ip_address = each.value.ip_address
|
||||
subnet = each.value.subnet
|
||||
|
||||
default_gateway_ip = each.value.default_gateway
|
||||
}
|
||||
|
||||
# 9. Puertos del firewall MX
|
||||
resource "meraki_appliance_port" "ports" {
|
||||
for_each = { for p in var.appliance_ports : p.port_id => p }
|
||||
|
||||
network_id = local.network_id
|
||||
port_id = each.value.port_id
|
||||
|
||||
enabled = each.value.enabled
|
||||
type = each.value.type
|
||||
vlan = each.value.vlan
|
||||
allowed_vlans = each.value.type == "trunk" ? each.value.allowed_vlans : null
|
||||
drop_untagged_traffic = each.value.drop_untagged_traffic
|
||||
}
|
||||
|
||||
@@ -112,6 +112,7 @@ variable "switch_port_configs" {
|
||||
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)
|
||||
}))
|
||||
@@ -127,6 +128,7 @@ variable "switch_stack_port_configs" {
|
||||
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)
|
||||
}))
|
||||
@@ -134,3 +136,56 @@ variable "switch_stack_port_configs" {
|
||||
description = "Puertos de stack a configurar por nombre. Terraform resuelve los seriales de todos los miembros automáticamente."
|
||||
}
|
||||
|
||||
# Configuración de puertos por nombre de switch (resolución dinámica de serial por nombre)
|
||||
variable "switch_named_port_configs" {
|
||||
type = list(object({
|
||||
switch_name = string # nombre exacto del switch en Meraki Dashboard
|
||||
port_range = string # puerto único "1" o rango "1-24"
|
||||
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."
|
||||
}
|
||||
|
||||
# VLAN de gestión de los switches del site
|
||||
variable "switch_management_vlan" {
|
||||
type = number
|
||||
default = null
|
||||
description = "VLAN ID de gestión para los switches del site (Dashboard > Switch > Switch settings > Management VLAN)"
|
||||
}
|
||||
|
||||
# Interfaces de enrutamiento L3 en stacks de switches
|
||||
variable "stack_routing_interfaces" {
|
||||
type = list(object({
|
||||
stack_name = string # nombre exacto del stack en Meraki Dashboard
|
||||
name = string # nombre descriptivo de la interfaz
|
||||
vlan_id = number
|
||||
ip_address = string # IP estática del stack en esta VLAN
|
||||
subnet = string # subred en formato CIDR, ej: "10.2.55.0/24"
|
||||
default_gateway = optional(string, null) # gateway para acceso a internet
|
||||
dns1 = optional(string, null) # DNS primario
|
||||
dns2 = optional(string, null) # DNS secundario
|
||||
}))
|
||||
default = []
|
||||
description = "Interfaces L3 (SVIs) en stacks de switches para acceso de gestión al Dashboard de Meraki."
|
||||
}
|
||||
|
||||
# Puertos del firewall MX
|
||||
variable "appliance_ports" {
|
||||
type = list(object({
|
||||
port_id = string
|
||||
enabled = optional(bool, true)
|
||||
type = optional(string, "access") # "access" o "trunk"
|
||||
vlan = optional(number, null) # VLAN nativa en trunk, o VLAN de acceso
|
||||
allowed_vlans = optional(string, "all") # solo para trunk
|
||||
drop_untagged_traffic = optional(bool, false)
|
||||
}))
|
||||
default = []
|
||||
description = "Configuración de puertos del firewall MX (LAN ports)."
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# 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"
|
||||
},
|
||||
]
|
||||
@@ -1,5 +1,16 @@
|
||||
# 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
|
||||
},
|
||||
{
|
||||
comment = "Bloqueo temporal switch a 8.8.8.8"
|
||||
policy = "deny"
|
||||
|
||||
@@ -32,4 +32,8 @@ module "bcn01_lab" {
|
||||
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
|
||||
}
|
||||
|
||||
@@ -119,4 +119,45 @@ switch_stack_port_configs = [
|
||||
vlan = 101 # GUEST
|
||||
access_policy_type = "Open"
|
||||
},
|
||||
{
|
||||
# Puerto 47: uplink trunk en ambos miembros del stack
|
||||
# VLAN nativa 109 (MANAGEMENT), permite todas las VLANs
|
||||
stack_name = "bcn01-lab-stack01"
|
||||
port_range = "47"
|
||||
name = "Uplink trunk"
|
||||
type = "trunk"
|
||||
vlan = 109 # MANAGEMENT - VLAN nativa (untagged)
|
||||
allowed_vlans = "all"
|
||||
access_policy_type = "Open"
|
||||
},
|
||||
]
|
||||
|
||||
# Puertos por nombre de switch (para configurar un miembro concreto del stack)
|
||||
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 = 110 # SERVERS
|
||||
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"
|
||||
},
|
||||
]
|
||||
|
||||
@@ -100,10 +100,11 @@ variable "switch_access_policies" {
|
||||
variable "switch_port_configs" {
|
||||
type = list(object({
|
||||
serial = string
|
||||
port_range = string # puerto único "1" o rango "1-24"
|
||||
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)
|
||||
}))
|
||||
@@ -111,7 +112,6 @@ variable "switch_port_configs" {
|
||||
description = "Puertos de switch a configurar con 802.1X. Requiere serial del switch."
|
||||
}
|
||||
|
||||
# Configuración de puertos por nombre de stack
|
||||
variable "switch_stack_port_configs" {
|
||||
type = list(object({
|
||||
stack_name = string
|
||||
@@ -119,9 +119,59 @@ variable "switch_stack_port_configs" {
|
||||
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."
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user