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
|
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
|
# Local para extraer el network_id exacto de la lista de redes
|
||||||
locals {
|
locals {
|
||||||
network_id = [for n in data.meraki_networks.net.items : n.id if n.name == var.network_name][0]
|
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
|
# Helper: expande un port_range en lista de port_ids
|
||||||
# "1-48" -> ["1","2",...,"48"] | "1" -> ["1"]
|
# "1-48" -> ["1","2",...,"48"] | "1" -> ["1"]
|
||||||
_expand_range = {
|
_expand_range = {
|
||||||
for config in concat(var.switch_port_configs, var.switch_stack_port_configs) :
|
for config in concat(var.switch_port_configs, var.switch_stack_port_configs, var.switch_named_port_configs) :
|
||||||
"${try(config.serial, config.stack_name)}:${config.port_range}" => (
|
"${try(config.serial, try(config.stack_name, config.switch_name))}:${config.port_range}" => (
|
||||||
length(split("-", config.port_range)) == 2
|
length(split("-", config.port_range)) == 2
|
||||||
? [for i in range(
|
? [for i in range(
|
||||||
tonumber(split("-", config.port_range)[0]),
|
tonumber(split("-", config.port_range)[0]),
|
||||||
@@ -45,6 +50,19 @@ locals {
|
|||||||
stack.name => stack.serials
|
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
|
# Expande switch_port_configs (serial explícito) en entradas individuales
|
||||||
switch_ports_expanded = flatten([
|
switch_ports_expanded = flatten([
|
||||||
for config in var.switch_port_configs : [
|
for config in var.switch_port_configs : [
|
||||||
@@ -55,6 +73,7 @@ locals {
|
|||||||
name = config.name
|
name = config.name
|
||||||
type = config.type
|
type = config.type
|
||||||
vlan = config.vlan
|
vlan = config.vlan
|
||||||
|
allowed_vlans = config.allowed_vlans
|
||||||
access_policy_type = config.access_policy_type
|
access_policy_type = config.access_policy_type
|
||||||
access_policy_number = config.access_policy_number
|
access_policy_number = config.access_policy_number
|
||||||
}
|
}
|
||||||
@@ -73,6 +92,7 @@ locals {
|
|||||||
name = config.name
|
name = config.name
|
||||||
type = config.type
|
type = config.type
|
||||||
vlan = config.vlan
|
vlan = config.vlan
|
||||||
|
allowed_vlans = config.allowed_vlans
|
||||||
access_policy_type = config.access_policy_type
|
access_policy_type = config.access_policy_type
|
||||||
access_policy_number = config.access_policy_number
|
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(
|
all_ports = merge(
|
||||||
{ for p in local.switch_ports_expanded : p.key => p },
|
{ 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
|
type = each.value.type
|
||||||
|
|
||||||
vlan = each.value.vlan
|
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_type = each.value.access_policy_type
|
||||||
access_policy_number = each.value.access_policy_number
|
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, "")
|
name = optional(string, "")
|
||||||
type = optional(string, "access")
|
type = optional(string, "access")
|
||||||
vlan = optional(number, null)
|
vlan = optional(number, null)
|
||||||
|
allowed_vlans = optional(string, "all")
|
||||||
access_policy_type = optional(string, "Open")
|
access_policy_type = optional(string, "Open")
|
||||||
access_policy_number = optional(number, null)
|
access_policy_number = optional(number, null)
|
||||||
}))
|
}))
|
||||||
@@ -127,6 +128,7 @@ variable "switch_stack_port_configs" {
|
|||||||
name = optional(string, "")
|
name = optional(string, "")
|
||||||
type = optional(string, "access")
|
type = optional(string, "access")
|
||||||
vlan = optional(number, null)
|
vlan = optional(number, null)
|
||||||
|
allowed_vlans = optional(string, "all")
|
||||||
access_policy_type = optional(string, "Open")
|
access_policy_type = optional(string, "Open")
|
||||||
access_policy_number = optional(number, null)
|
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."
|
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
|
# Reglas de firewall L3
|
||||||
firewall_rules = [
|
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"
|
comment = "Bloqueo temporal switch a 8.8.8.8"
|
||||||
policy = "deny"
|
policy = "deny"
|
||||||
|
|||||||
@@ -32,4 +32,8 @@ module "bcn01_lab" {
|
|||||||
switch_access_policies = var.switch_access_policies
|
switch_access_policies = var.switch_access_policies
|
||||||
switch_port_configs = var.switch_port_configs
|
switch_port_configs = var.switch_port_configs
|
||||||
switch_stack_port_configs = var.switch_stack_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
|
vlan = 101 # GUEST
|
||||||
access_policy_type = "Open"
|
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" {
|
variable "switch_port_configs" {
|
||||||
type = list(object({
|
type = list(object({
|
||||||
serial = string
|
serial = string
|
||||||
port_range = string # puerto único "1" o rango "1-24"
|
port_range = string
|
||||||
name = optional(string, "")
|
name = optional(string, "")
|
||||||
type = optional(string, "access")
|
type = optional(string, "access")
|
||||||
vlan = optional(number, null)
|
vlan = optional(number, null)
|
||||||
|
allowed_vlans = optional(string, "all")
|
||||||
access_policy_type = optional(string, "Open")
|
access_policy_type = optional(string, "Open")
|
||||||
access_policy_number = optional(number, null)
|
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."
|
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" {
|
variable "switch_stack_port_configs" {
|
||||||
type = list(object({
|
type = list(object({
|
||||||
stack_name = string
|
stack_name = string
|
||||||
@@ -119,9 +119,59 @@ variable "switch_stack_port_configs" {
|
|||||||
name = optional(string, "")
|
name = optional(string, "")
|
||||||
type = optional(string, "access")
|
type = optional(string, "access")
|
||||||
vlan = optional(number, null)
|
vlan = optional(number, null)
|
||||||
|
allowed_vlans = optional(string, "all")
|
||||||
access_policy_type = optional(string, "Open")
|
access_policy_type = optional(string, "Open")
|
||||||
access_policy_number = optional(number, null)
|
access_policy_number = optional(number, null)
|
||||||
}))
|
}))
|
||||||
default = []
|
default = []
|
||||||
description = "Puertos de stack a configurar por nombre. Terraform resuelve los seriales automáticamente."
|
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