La API de Meraki requiere encryption_mode="wpa" cuando auth_mode="psk", además de wpa_encryption_mode. Sin este campo la API devuelve el error "Pre-shared key mode requires a valid encryption mode (wep, wpa)". Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
201 lines
7.6 KiB
Terraform
Executable File
201 lines
7.6 KiB
Terraform
Executable File
# Definición de la Organización
|
|
variable "organization_name" {
|
|
type = string
|
|
description = "Nombre exacto de tu organización en el Dashboard de Meraki"
|
|
}
|
|
|
|
# Definición de la Red
|
|
variable "network_name" {
|
|
type = string
|
|
description = "Nombre de la red (Network)"
|
|
}
|
|
|
|
|
|
# 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 = "Reglas de firewall L3 para el site. Se aplican en orden, antes de la regla allow-all implícita de Meraki"
|
|
}
|
|
|
|
# SSIDs wireless
|
|
variable "wireless_ssids" {
|
|
type = list(object({
|
|
number = number
|
|
name = string
|
|
enabled = optional(bool, true)
|
|
auth_mode = string
|
|
psk = optional(string, null) # Contraseña WPA2/WPA3-PSK (sensible, usar TF_VAR o secret)
|
|
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"
|
|
}
|
|
|
|
# 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"
|
|
}
|
|
|
|
variable "wifi_password_psk" {
|
|
type = string
|
|
description = "Password para la SSID WPA2 desde GitHub Secrets"
|
|
sensitive = true
|
|
}
|
|
|
|
# Definición del mapa de VLANs
|
|
variable "switch_vlans" {
|
|
type = map(object({
|
|
name = string
|
|
subnet = optional(string, null) # null para VLANs sin L3 (p.ej. WAN puro switching)
|
|
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 = "VLANs para el site"
|
|
|
|
validation {
|
|
condition = alltrue([
|
|
for v in values(var.switch_vlans) :
|
|
contains(["Run a DHCP server", "Relay DHCP to another server", "Do not respond to DHCP requests"], v.dhcp_handling)
|
|
])
|
|
error_message = "dhcp_handling debe ser uno de: 'Run a DHCP server', 'Relay DHCP to another server', 'Do not respond to DHCP requests'."
|
|
}
|
|
}
|
|
|
|
# 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. El shared secret se toma de radius_secret."
|
|
}
|
|
|
|
# Configuración de puertos de switch con 802.1X
|
|
# Requiere serial del switch (visible en Dashboard > Switches > nombre del switch)
|
|
variable "switch_port_configs" {
|
|
type = list(object({
|
|
serial = string
|
|
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. access_policy_number referencia el número de la política creada en switch_access_policies."
|
|
}
|
|
|
|
# Configuración de puertos por nombre de stack (resolución dinámica de seriales)
|
|
variable "switch_stack_port_configs" {
|
|
type = list(object({
|
|
stack_name = string # nombre exacto del stack en Meraki Dashboard
|
|
port_range = string # puerto único "1" o rango "1-48"
|
|
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 de todos los miembros automáticamente."
|
|
}
|
|
|
|
# Configuración de puertos por nombre de switch (resolución dinámica de serial)
|
|
# Útil para configurar un miembro específico de un stack sin conocer el serial
|
|
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)."
|
|
}
|
|
|