La gema netsnmp proporciona una implementación nativa de Ruby del protocolo SNMP (V1/2C ABD V3).
Agregue esta línea al archivo gem de su aplicación:
gem 'netsnmp'Y luego ejecutar:
$ bundle
O instálelo usted mismo como:
$ gem install netsnmp
Esta joya proporciona:
Si busca gemas SNMP en Ruby Toolbox, encontrará un grupo. Puede preguntar, ¿por qué no usar uno de ellos?
La mayoría de ellos solo implementan V1 y V2, por lo que si su requisito es usar V3, solo tiene 2 opciones: Net-SNMP (inmantivado desde 2013) y su seguimiento Net-SNMP2, que comenzó como una horquilla para arreglar algunos errores que quedan desatendidos. Ambas bibliotecas envuelven la biblioteca C NETSNMP usando FFI, lo que las deja vulnerables a los siguientes errores (experimentado en ambas bibliotecas):
Todos estos problemas se resuelven aquí.
Puede usar el contenedor Docker proporcionado en Spec/Support para probar con estos ejemplos (el puerto utilizado en los ejemplos debe ser el puerto externo Docker asignado al puerto 161).
require 'netsnmp'
# example you can test against the docker simulator provided. port attribute might be different.
manager = NETSNMP :: Client . new ( host : "localhost" , port : 33445 , username : "simulator" ,
auth_password : "auctoritas" , auth_protocol : :md5 ,
priv_password : "privatus" , priv_protocol : :des ,
context : "a172334d7d97871b72241397f713fa12" )
# SNMP get
manager . get ( oid : "sysName.0" ) #=> 'tt'
# SNMP walk
# sysORDescr
manager . walk ( oid : "sysORDescr" ) . each do | oid_code , value |
# do something with them
puts "for #{ oid_code } : #{ value } "
end
manager . close
# SNMP set
manager2 = NETSNMP :: Client . new ( host : "localhost" , port : 33445 , username : "simulator" ,
auth_password : "auctoritas" , auth_protocol : :md5 ,
priv_password : "privatus" , priv_protocol : :des ,
context : "0886e1397d572377c17c15036a1e6c66" )
# setting to 43, becos yes
# sysUpTimeInstance
manager2 . set ( "1.3.6.1.2.1.1.3.0" , value : 43 )
manager2 . closeLos ejemplos SNMP V2/V1 serán similares (tenga cuidado con las diferencias en los atributos de inicialización).
Todos los ejemplos anteriores se realizaron especificando tipos primitivos, es decir, a menos que se especifique lo contrario, intentará convertir un tipo "primitivo" de rubí a un tipo ASN.1 primitivo y viceversa:
Eso significa que, si pasa value: 43 a la llamada #set , va a construir una varbind con un entero ASN.1. Si emite un #get y la respuesta contiene un entero ASN.1, devolverá un entero.
Sin embargo, SNMP define los tipos ASN.1 específicos de la aplicación, para los cuales hay soporte, aunque limitado. Actualmente, hay soporte para direcciones IP y horarios.
Si crea un objeto IPAddr (Ruby Standard Library ipaddr ) y lo pasa a la llamada #set , se asignará al código específico de contenido SNMP. Si la respuesta de una llamada #get contiene una dirección IP, se asignará a un objeto IPAddr .
El tipo NETSNMP::Timeticks es interno para esta biblioteca, pero es un tipo Numeric Ruby. Es seguro usarlo "como numérico", es decir, realizar cálculos.
Los tipos Counter32 y Counter64 se asignarán a enteros simples.
Puede encontrar ejemplos de uso aquí. Si necesita soporte para un tipo que falta, tiene las siguientes opciones:
:type parámetro en las llamadas #set : # as a symbol
manager . set ( "somecounteroid" , value : 999999 , type : :counter64 )
# as the SNMP specific type id, if you're familiar with the protocol
manager . set ( "somecounteroid" , value : 999999 , type : 6 ) netsnmp cargará los MIBS predeterminados de los directorios conocidos o anunciados (a través de MIBDIRS ) (siempre que estén instalados en el sistema). Estos se utilizarán para la conversión OID.
A veces necesitará cargar más, sus propios MIBS, en cuyo caso, puede usar la siguiente API:
require "netsnmp"
NETSNMP :: MIB . load ( "MY-MIB" )
# or, if it's not in any of the known locations
NETSNMP :: MIB . load ( "/path/to/MY-MIB.txt" )Puede instalar SNMP MIBS común utilizando su Administrador de paquetes:
# using apt-get
> apt-get install snmp-mibs-downloader
# using apk
> apk --update add net-snmp-libs
En Ruby, generalmente se le aconseja que no comparta objetos IO en los hilos. El mismo principio se aplica aquí a NETSNMP::Client : siempre que lo use dentro de un hilo de ejecución, debe comportarse de manera segura. Entonces, algo como esto sería posible:
general_options = { auth_protocol : ... .
routers . map do | r |
Thread . start do
NETSNMP :: Client . new ( general_options . merge ( host : r ) ) do | cl |
cli . get ( oid : " 1.6 . 3 ...... .
end
end
end . each ( & :join ) Evented IO también es compatible, ya que puede pasar un objeto :proxy como un canal de comunicación ya abierto al cliente. Muy importante: debe cuidar el ciclo de vida, ya que el cliente no se conectará y no cerrará el objeto, no asumirá que no hay control sobre él.
Al pasar un objeto proxy, puede omitir el parámetro :host .
El objeto proxy tendrá que ser un #send de implementación de tipo pato, que es un método que recibe la carga útil de envío de PDU y devolver la carga útil de la PDU receptora.
Aquí hay un pequeño ejemplo de pseudocódigo:
# beware, we are inside a warp-speed loop!!!
general_options = { auth_protocol : ... .
proxy = SpecialUDPImplementation . new ( host : router )
NETSNMP :: Client . new ( general_options . merge ( proxy : proxy ) ) do | cl |
# this get call will eventually #send to the proxy...
cli . get ( oid : " 1.6 . 3 ...... .
end
# client isn't usable anymore, but now we must close to proxy
proxy . closePara obtener más información sobre este tema, las especificaciones prueban esta característica contra el celuloide-io. Se podría agregar una EventMachine, si alguien sería lo suficientemente amable como para proporcionar una implementación.
Esta biblioteca tiene algunas soluciones a algunas características faltantes en el lenguaje Ruby, a saber, la inexistencia de una estructura de matriz de bytes. Lo más cercano que tenemos es una corriente de byte presentada como una cadena con codificación ASCII. Se agregó un método a la clase de cadena llamada #xor para algunas operaciones necesarias internamente. Para evitar que se han empleado parches de mono innecesarios, se han empleado refinamientos.
Si #xor se convierte en algún momento en el cuello de botella de su uso, esta gema también es compatible con Xorcist. Solo tiene que agregarlo a su archivo gem (o instalarlo en el sistema):
# Gemfile
gem 'netsnmp'
# or, in the command line
$ gem install netsnmp
y netsnmp lo recogerá automáticamente.
Si usa esta gema a menudo con SNMP V3 y Auth/Priv Security Level habilitado, tendrá la sensación divertida de que todo podría ser un poco más rápido. Bueno, esto se debe básicamente a que el verdadero cuello de botella de rendimiento de esta gema es la generación de las claves de autenticación y pase utilizadas para la autorización y el cifrado. Aunque esto es algo único para cada cliente, su retraso será notable si se ejecuta en> 100 hosts.
Hay una solución al principio recomendada, pero esto solo se puede usar si está utilizando el mismo usuario/AuthPass/PrivPass en todos los hosts. . Use esto con cuidado, entonces:
$shared_security_parameters = NETSNMP :: SecurityParameters . new ( security_level : :authpriv , username : "mustermann" ,
auth_protocol : :md5 , priv_protocol : :aes , ... .
# this will eager-load the auth/priv_key
...
# over 9000 routers are running on this event loop!!! this is just one!
NETSNMP :: Client . new ( share_options . merge ( proxy : router_proxy , security_parameters : $shared_security_parameters . dup ) . new do | cl |
cli . get ( oid : .....
end Esta biblioteca es compatible y se prueba contra las versiones de Ruby 2.1 o más recientes, incluido Ruby 3. También es compatible y prueba contra Truffleruby.
Todas las codificaciones/decodificaciones/cifrado/descifrado/digestos se realizan utilizando openssl , que es (aún) una parte de la biblioteca estándar. Si en algún momento openssl se elimina y no se distribuye específicamente, tendrá que instalarlo usted mismo. Ojalá esto nunca suceda.
También utiliza la API openssl ASN.1 para codificar/decodificar Bers, que se sabe que es estricto, y es posible que no pueda decodificar PDU si no cumple con el RFC compatible.
Puede establecer el NETSNMP_DEBUG en el nivel de depuración desidido (actualmente, 1 y 2). Los registros se escribirán en Stderr.
También puede configurarlo para un cliente específico:
manager2 = NETSNMP :: Client . new ( debug : $stderr , debug_level : 2 , ... . ) Esta biblioteca usa RSPEC. Las especificaciones del cliente son pruebas de "integración", ya que nos comunicamos con un simulador de agente SNMP construido por SNMPSIM.
Puede ejecutar todas las pruebas escribiendo:
> bundle exec rake spec
# or
> bundle exec rspec
...
La forma más directa de ejecutar las pruebas es mediante el uso de la configuración docker-compose (que también es lo que se usa en el CI). Ejecutarlo contra la versión de Ruby que se dirige:
> docker-compose -f docker-compose.yml -f docker-compose-ruby-${RUBY_MAJOR_VERSION}.${RUBY_MAJOR_VERSION}.yml run netsnmp
El CI ejecuta las pruebas contra todas las versiones de Ruby compatibles. Si los cambios rompen una versión específica de Ruby, asegúrese de comprometer los cambios apropiados que abordan el caso de borde o avíseme en el tablero de problemas, para que pueda ayudarlo.
El simulador SNMP se ejecuta en su propio contenedor en la configuración docker .
Puede instalar el paquete usted mismo (Ej: pip install snmpsim ) y ejecutar el servidor localmente, y luego establecer la variable de entorno SNMP_PORT , donde se está ejecutando el simulador SNMP.
El trabajo del CI es:
Hay algunas características que esta joya no es compatible. Fue construido para proporcionar una implementación de cliente (o gerente, en lenguaje SNMP) solamente, y los requisitos se cumplieron. Sin embargo, estas fallas notables se destacarán:
Entonces, si le gusta la gema, pero prefiere implementar estas características, ayude enviándonos un PR y con mucho gusto lo revisaremos.