[A06] Resolución BUG SSH Legacy en info.rb, conclusión F1 de Compresión XVA, y actualizaciones de métricas y planes.

This commit is contained in:
Ricardo Monla
2026-04-10 19:12:37 -03:00
parent 941da87ed2
commit 15bcf81183
14 changed files with 855 additions and 23 deletions
+84 -3
View File
@@ -122,8 +122,8 @@ module ADN
contexto_str = contexto.any? ? " [#{contexto.join(' ')}]" : ""
@logger.info("Conectando a #{nodo_nombre}#{contexto_str} (#{config[:ip]}:#{config[:puerto_ssh]})")
# Autorizar candados
autorizar_candados
# Autorizar candados solo si es necesario (password o passphrase)
autorizar_candados unless config[:auth_type] == :rsa_legacy
case config[:auth_type]
when :passphrase
@@ -132,16 +132,26 @@ module ADN
ejecutar_con_password(nodo_nombre, config, comando_remoto)
when :rsa
ejecutar_con_rsa(nodo_nombre, config, comando_remoto)
when :rsa_legacy
ejecutar_con_rsa_legacy(nodo_nombre, config, comando_remoto)
end
end
def obtener_config(nodo_nombre)
meta = ADN::NodosInfo.extraer_metadata(nodo_nombre)
return nil unless meta && meta[:ip] && meta[:usuario] && meta[:clave_boveda]
return nil unless meta && meta[:ip] && meta[:usuario]
# Extraer IP de LAN si está disponible en la ficha
meta[:ip_lan] = ADN::NodosInfo.extraer_ip_lan(nodo_nombre)
# Extraer clave SSH específica (para nodos con múltiples claves)
ruta = File.join(ADN::NODOS_DIR, "#{nodo_nombre}.md")
contenido = File.read(ruta, encoding: 'UTF-8') if File.exist?(ruta)
if contenido
meta[:clave_ssh] = ADN::NodosInfo.detectar_clave_ssh(contenido)
meta[:ssh_opts] = ADN::NodosInfo.detectar_ssh_opts(contenido)
end
# Inferir proxy: si el nodo tiene host (es VM), usar el host como proxy
if meta[:host] && meta[:host] != nodo_nombre
proxy_meta = ADN::NodosInfo.extraer_metadata(meta[:host])
@@ -360,6 +370,77 @@ module ADN
end
end
def ejecutar_con_rsa_legacy(nodo_nombre, config, comando_remoto)
# XenServer 7.0 (OpenSSH 6.6.1) requiere algoritmos legacy ssh-rsa (SHA-1)
proxy_config = config[:proxy] ? ADN::NodosInfo.extraer_metadata(config[:proxy]) : nil
# Determinar clave SSH específica si está configurada
clave_ssh = File.expand_path(config[:clave_ssh] || "~/.ssh/id_rsa")
@logger.info("Usando clave SSH: #{clave_ssh}")
ssh_target = "#{config[:usuario]}@#{config[:ip]}"
# Opciones SSH legacy para OpenSSH < 7.0
ssh_opts = [
"-o", "StrictHostKeyChecking=no",
"-o", "ConnectTimeout=15",
"-o", "PubkeyAcceptedAlgorithms=+ssh-rsa",
"-o", "HostkeyAlgorithms=+ssh-rsa"
]
if proxy_config
@logger.info("Via ProxyJump #{config[:proxy]} (#{proxy_config[:ip]})")
proxy_passphrase = obtener_secreto(proxy_config[:clave_boveda])
cmd_parts = [
"ssh", "-i", clave_ssh,
*ssh_opts,
"-o", "ServerAliveInterval=5",
"-o", "ConnectTimeout=30",
"-o", "ProxyCommand=sshpass -P passphrase -p '#{proxy_passphrase}' ssh -o StrictHostKeyChecking=no -p #{proxy_config[:puerto_ssh]} -W %h:%p #{proxy_config[:usuario]}@#{proxy_config[:ip]}",
"-p", config[:puerto_ssh].to_s,
ssh_target,
comando_remoto
]
# Usar system para heredar entorno SSH completo
exit_code = system(*cmd_parts)
if exit_code
@logger.exito("Comando ejecutado exitosamente en #{nodo_nombre} (RSA legacy)")
else
ADN::ErrorHandler.error("Fallo en ejecución remota")
exit 1
end
elsif @opciones[:interactivo]
@logger.info("Abriendo sesión interactiva a #{nodo_nombre} (RSA legacy)...")
cmd = "ssh -i #{clave_ssh} #{ssh_opts.join(' ')} -p #{config[:puerto_ssh]} #{ssh_target}"
exec(cmd)
else
# Usar script bash para asegurar que el entorno SSH se herede correctamente
script = <<~BASH
#!/bin/bash
ssh -i #{clave_ssh} #{ssh_opts.join(' ')} -p #{config[:puerto_ssh]} #{ssh_target} '#{comando_remoto.gsub("'", "'\\''")}'
BASH
tmpscript = "/tmp/.adn_ssh_rsa_legacy_#{Process.pid}.sh"
File.write(tmpscript, script)
File.chmod(0700, tmpscript)
# Ejecutar con bash para heredar entorno
exit_code = system("/bin/bash", tmpscript)
File.delete(tmpscript) if File.exist?(tmpscript)
if exit_code
@logger.exito("Comando ejecutado exitosamente en #{nodo_nombre} (RSA legacy)")
else
ADN::ErrorHandler.error("Fallo en ejecución remota")
exit 1
end
end
end
def listar_nodos
puts "#{Color::CYAN}📡 Nodos SSH disponibles (leídos de fichas nodos/*.md):#{Color::RESET}"
puts "#{Color::DIM}#{'─' * 75}#{Color::RESET}"