Skip to content

Commit

Permalink
Meet SNMP Command Responder \o/
Browse files Browse the repository at this point in the history
The tool runs one or more SNMP command responders (agents) and
one or more trees of MIB objects representing SNMP-managed entities.
Received messages are applied onto one of the MIB trees chosen by
tool's configuration.

As of this initial version, the basic functionality seems to
work, however:

* the plugin feature is not fully implemented
* GETNEXT/GETBULK performance needs to be improved
* network transparency is not operational
* documentation on MIB hooks population is lacking
* many imaginable configuration examples are not present
* pysnmp API needs minor tweaks it seems
* unit tests is a highly desired thing
  • Loading branch information
etingof committed Jan 13, 2019
1 parent 194308a commit 628247d
Show file tree
Hide file tree
Showing 37 changed files with 4,551 additions and 29 deletions.
7 changes: 5 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ celerybeat-schedule

# Environments
.env
.venv
.venv*
env/
venv/
venv*
ENV/
env.bak/
venv.bak/
Expand All @@ -102,3 +102,6 @@ venv.bak/

# mypy
.mypy_cache/

# PyCharm
.idea/
21 changes: 21 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

Revision 0.0.0, released 13-01-2019
-----------------------------------

- Initial public release

As of this release, the SNMP Command Responder tool can run one or
more SNMP agents and maintain one or more trees of MIB objects
representing SNMP-managed entities. Received messages are applied
onto one of the MIB trees chosen by tool's configuration.

As of this initial version, the basic functionality seems to
work, however:

* the plugin feature is not fully implemented
* GETNEXT/GETBULK performance needs to be improved
* network transparency is not operational
* the documentation is up, though still lacking at places
* many imaginable configuration examples are not yet present
* apparently, pysnmp 5.x API needs minor tweaks
* unit tests is a highly desired thing
25 changes: 0 additions & 25 deletions LICENSE

This file was deleted.

24 changes: 24 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Copyright (c) 2019, Ilya Etingof <etingof@gmail.com>
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
6 changes: 6 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
include *.txt *.md
recursive-include docs/source *.rst *.svg *.py
recursive-include docs *.conf Makefile
recursive-include conf *.conf *.py
recursive-include plugins *.py
prune docs/build
68 changes: 66 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,66 @@
# snmpresponder
Cross-platform, extendable SNMP responder

SNMP Command Responder
----------------------

[![PyPI](https://img.shields.io/pypi/v/snmpresponder.svg?maxAge=2592000)](https://pypi.org/project/snmpresponder)
[![Python Versions](https://img.shields.io/pypi/pyversions/snmpresponder.svg)](https://pypi.org/project/snmpresponder/)
[![Status](https://img.shields.io/pypi/status/snmpresponder.svg)](https://github.com/etingof/snmpresponder/)
[![Build status](https://travis-ci.org/etingof/snmpresponder.svg?branch=master)](https://travis-ci.org/etingof/snmpresponder)
[![GitHub license](https://img.shields.io/badge/license-BSD-blue.svg)](https://raw.githubusercontent.com/etingof/snmpresponder/master/LICENSE.txt)

The SNMP Command Responder daemon runs one or more SNMP agents and maintains
one or more trees of SNMP managed objects (i.e. MIBs). The user can interface
those managed objects with the data they are willing to serve over SNMP.

SNMP requests received by any of the embedded SNMP agents can be routed to
any of the MIB trees for processing via a declarative mini-language.

The use-case for SNMP Command Responder is to serve user data over
SNMP.

Features
--------

* SNMPv1/v2c/v3 operations with built-in protocol and transport translation capabilities
* SNMPv3 USM supports MD5/SHA/SHA224/SHA256/SHA384/SHA512 auth and
DES/3DES/AES128/AES192/AES256 privacy crypto algorithms
* Supports all SNMP commands
* Maintains multiple independent SNMP engines, network transports and MIB trees
* Offers versatile SNMP PDU routing towards a MIB tree implementation
* Supports asynchronous MIB objects API
* Extension modules supporting SNMP PDU filtering and on-the-fly modification
* Works on Linux, Windows and OS X

Download & Install
------------------

SNMP Command Responder software is freely available for download from
[PyPI](https://pypi.org/project/snmpresponder).

Just run:

```bash
$ pip install snmpresponder
```

Alternatively, you can get it from [GitHub](https://github.com/etingof/snmpresponder/releases).

How to use SNMP Command Responder
---------------------------------

First you need to configure the tool. It is largely driven by
[configuration files](http://snmplabs.com/snmpresponder/configuration/index.html)
written in a declarative mini-language. To help you started, we maintain
[a collection](http://snmplabs.com/snmpresponder/configuration/index.html#examples)
of configuration files designed to serve specific use-cases.

Getting help
------------

If something does not work as expected or we are missing an interesting feature,
[open an issue](https://github.com/etingof/snmpresponder/issues) at GitHub or
post your question [on Stack Overflow](https://stackoverflow.com/questions/ask).

Finally, your PRs are warmly welcome! ;-)

Copyright (c) 2019, [Ilya Etingof](mailto:etingof@gmail.com). All rights reserved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
"""SNMP MIB module (SNMPv2-MIB) expressed in pysnmp data model.
This Python module is designed to be imported and executed by the
pysnmp library.
See http://snmplabs.com/pysnmp for further information.
Notes
-----
ASN.1 source file:///usr/share/snmp/mibs/SNMPv2-MIB.txt
Produced by pysmi-0.4.0 at Sun Jan 13 09:39:06 2019
On host igarlic platform Darwin version 17.7.0 by user ilya
Using Python version 3.6.0 (v3.6.0:41df79263a11, Dec 22 2016, 17:23:13)
"""
import socket


if 'mibBuilder' not in globals():
import sys

sys.stderr.write(__doc__)
sys.exit(1)


MibScalarInstance, = mibBuilder.importSymbols(
'SNMPv2-SMI',
'MibScalarInstance'
)

# Import Managed Objects to base Managed Objects Instances on

(sysName,) = mibBuilder.importSymbols(
"SNMPv2-MIB",
"sysName"
)


# MIB Managed Objects in the order of their OIDs


class SysnameObjectInstance(MibScalarInstance):
def readTest(self, varBind, **context):
# Just confirm that this MIB object instance is available
cbFun = context['cbFun']
cbFun(varBind, **context)

def readGet(self, varBind, **context):
cbFun = context['cbFun']

name, value = varBind

# Initialize response value from *gethostname()* return
value = self.syntax.clone(socket.gethostname())

cbFun((name, value), **context)

def readTestNext(self, varBind, **context):
name, value = varBind

if name >= self.name:
# This object does not qualify as "next*, pass the call
MibScalarInstance.readTestNext(self, varBind, **context)

else:
# Confirm this object is available and report its OID
cbFun = context['cbFun']
cbFun((self.name, value), **context)

def readGetNext(self, varBind, **context):
name, value = varBind

if name >= self.name:
# This object does not qualify as "next*, pass the call
MibScalarInstance.readGetNext(self, varBind, **context)

else:
cbFun = context['cbFun']

# Initialize response value from *gethostname()* return
value = self.syntax.clone(socket.gethostname())

cbFun((self.name, value), **context)

_sysName = SysnameObjectInstance(
sysName.name,
(0,),
sysName.syntax
)

# Export Managed Objects Instances to the MIB builder

mibBuilder.exportSymbols(
"__SNMPv2-MIB",
**{"sysName": _sysName}
)
56 changes: 56 additions & 0 deletions conf/single-agent-single-mib-tree/plugins/logger.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#
# SNMP Proxy Forwarder: logger plugin configuration
#

[general]
# log into a file
#method: file

# log through syslog
#method: syslog

# log into main process log
#method: snmpfwd

# inhibit any logging
#method: null

# logging level: debug, info, error
#level: info

[file]
# log into this file
destination: /tmp/snmpfwd-brief.log

# use time-based file rotation
#rotation: timed

# keep up to this number of logs upon rotation
#backupcount: 30

# rotate each day
#timescale: D
#interval: 1

[syslog]
# syslog transport: udp, tcp, socket or path to syslog socket
#transport: socket

# syslog facility (see `man syslog`)
#facility: daemon

# use non-local syslog
#host: localhost

# non-default syslog port
#port: 514

[content]
# log these PDU types
#pdus: GetRequest GetNextRequest SetRequest GetBulkRequest InformRequest SNMPv2Trap Response

# log message template
#template: ${isotime} ${callflow-id} ${snmp-peer-address} ${snmp-pdu-type} ${snmp-var-binds}

# values in var-binds can be surrounded by these tokens
#parentheses: " "
59 changes: 59 additions & 0 deletions conf/single-agent-single-mib-tree/snmpresponderd.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#
# SNMP Command Responder configuration file
#

config-version: 1
program-name: snmpresponder

snmp-credentials-group {
snmp-transport-domain: 1.3.6.1.6.1.1.100
snmp-bind-address: 127.0.0.1:1161

snmp-engine-id: 0x0102030405070809

snmp-community-name: public
snmp-security-name: public
snmp-security-model: 2
snmp-security-level: 1

snmp-credentials-id: snmp-credentials
}

context-group {
snmp-context-engine-id-pattern: .*?
snmp-context-name-pattern: .*?

snmp-context-id: any-context
}

content-group {
snmp-pdu-type-pattern: .*?
snmp-pdu-oid-prefix-pattern-list: .*?

snmp-content-id: any-content
}

peers-group {
snmp-transport-domain: 1.3.6.1.6.1.1.100
snmp-bind-address-pattern-list: .*?
snmp-peer-address-pattern-list: .*?

snmp-peer-id: 100
}

managed-objects-group {
mib-text-search-path-list: http://mibs.snmplabs.com/asn1/
mib-code-modules-pattern-list: conf/single-agent-single-mib-tree/managed-objects/.*py[co]?

mib-tree-id: managed-objects-1
}

routing-map {
matching-snmp-context-id-list: any-context
matching-snmp-content-id-list: any-content

matching-snmp-credentials-id-list: snmp-credentials
matching-snmp-peer-id-list: 100

using-mib-tree-id: managed-objects-1
}
2 changes: 2 additions & 0 deletions devel-requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Sphinx <= 1.6; python_version < '2.7'
Sphinx > 1.6; python_version >= '2.7'
Loading

0 comments on commit 628247d

Please sign in to comment.