snmp_rust_agent 0.4.0

A framework for building SNMP v3 Agents
Documentation
//!# SNMP v3 Agent framework
//! This is work towards a framework for developing SNMP v3 agents, using the rasn ASN-1 library for decoding the
//!  on the wire data. While a manager (effectively a client) has to support a range of legacy agents,
//!  an agent (e.g. server) can offer a subset of features and still be useful.
//!
//! This agent only supports SNMP v3, older variants have no on the wire security.
//!
//! This project follows semver - but that means no guarantees at all pre v1! There are changes in the internal APIs
//!  and traits in this release, so this is a minor version (0.4.0) rather than a patch.
//!
//! The standards define the use of horrible old crypto types like single DES for privacy, and
//! MD5 in the authentication. The code currently supports HMAC-SHA-1-96, the stronger hashes
//! from RFC-7630 and AES-128. There is no agreed standard for stronger ciphers. It is not clear that
//! using stronger hash functions or ciphers will deliver significant advantages in practice. The well
//! known collision weakness of SHA-1 is not a problem in an HMAC application.
//!
//! This release implements (more or less) the transaction model for Set PDUs. This required a change to the
//! OidKeeper trait, defined in src/keeper.rs. The sample handlers, and the Rust MIB compiler have been updated
//!  to follow this.
//!
//! The agent server loop is a single threaded blocking design. I would argue that this is appropriate for almost
//! all agents, as typically a single manager will interact with multiple agents. Managers may well want to support
//! high levels of concurrency. The single threaded design avoids many issues with concurrency and locking.
//! Of course, there is nothing to stop handlers for specific long running operations using a thread.
//!
//! The 0.2.1 release introduced a more flexible and capable permissions model, driven by a policy in a TOML
//! file. Different groups of users can be given selective access to different parts of the MIB, with independent
//! control of read and write access. This has been extended to support multiple contexts in this release. By
//! default, rules apply to all contexts, but you can mark a rule as applying to a specific context.  The
//! integration of this permissions model into GetNext handling is fixed.
//!
//! In this release the Engine ID is loaded from a configuration file. A sample configuration file is included
//! at .snmp-agent.conf.
//!
//! Two example MIB module handlers are included under src/handlers for SNMPv3-MIB and SNMP-USER-BASED-SM-MIB.
//! They were written based on stubs generated by the Rust tool. The USM handler does not yet include
//! remote password changes and user creation.
//!
//! Commented out Module Compliance statements are generated by the stub generator. If you FULLY implement
//! the mandatory features you can un-comment, and your module will appear in the sysORTable. Some managers
//! might even do something useful with that!
//!
//! There is no usable support for notifications so far, although I am thinking about it, and the start of
//! some code in src/notifier.rs. Don't take that seriously, I will probably do something completely
//! different when I understand the problem better. Please raise an issue or start a discussion if you have
//! a specific use case in mind, as that would really help me decide how to do it.
//!
//! There are known limitations for tables that use either the AUGMENTS or use index columns drawn from foreign
//! tables. The generated stubs have a single row of junk data in all tables. For most tables, that row is
//! indexed correctly. For tables that foreign index columns, an arbitrary single integer index is used, with
//! the row indexed at value 1. This allows operations like get and get_next to work. If you take that stub and
//! implement it as real handler, you will need to do your own implementation of foreign indexing,
//! almost certainly involving referencing the other table structs.
//!
//!## Users and passwords
//!
//! There is a small python tool for generating a username and password file under tools/usekey.py. It now reads
//! the Engine Id from the configuration file.
//!
//! Changing passwords on the wire is implemented. User creation is not.
//!
//!## Tools for stub generation
//!
//! At present, there is prototype tooling to help implement an useful agent, but it is possible with some
//! patience. There is a stub generator, written in Rust.
//!
//! The source files for the Rust stub generator are under src/bin/stub-gen. It uses the nom parser combinator
//! library for parsing. It has a reasonably complete parser implementation, which can parse almost all the MIBs
//! on my machine except for legacy MIBS in Smi v1 and a few bootstrap definition files. The code generator in this
//! version ignores everything to do with notifications (but does detailed parsing).  It also does the wrong thing
//! with AUGMENTS and tables that use foreign index columns (AUGMENTS is actually just a
//! special case of foreign indices).
//!
//! The stub generator now sorts items by Oid order, so as to give stable output.
//!
//!## Workflow
//! First build the stub generator with:
//!
//! ```shell
//! cargo build --bin stub-gen
//! ```
//!
//! then generate the stubs for the mibs you want with:
//!
//! ```shell
//! target/debug/stub-gen -o src/stubs/ MIB1 MIB2 ...
//! ```
//!
//! where MIB1 and MIB2 and so on are the names of the MIB files to generate stubs from. The generator searches
//! /var/lib/mibs/ietf, /var/lib/mibs/iana and /usr/share/snmp/mibs to find the files, and tries adding .txt
//! extension as well. If your system has the files somewhere different, or you wish to include vendor mibs,
//! you can use ```-p``` or ```-path``` flags to override this built in default as many times as you need.
//! For example, ```-p /usr/lib/mibs/ -p /var/lib/mibs/ietf/```. If you use the flag, the builtin default is
//! ignored, and you will have to populate the whole path. If you might have name clashes, the path is search
//! in the obvious order, and the first matching file is used.
//!
//! By default, the stub generator ignores objects that are marked as "deprecated" or "obsolete" in the MIB.
//! You can include deprecated objects with the ```-d``` or ```--deprecated``` flags. If you really need to implement
//! something obsolete, there is a ```--obsolete``` flag, if you are stuck with a manager that can't be
//! updated and depends on some old stuff.
//!
//! The generated stubs will be placed under src/stubs/ with the command above.
//!
//! If you want the agent to do something useful, you need to write your own back-end implementations. The generated stubs are placed in the
//! src/stubs/ directory. The basic idea is to associate instances that support the OidKeeper trait with the OID value or values that they
//! support in the OidMap. This is populated and then the agent loop_forever() runs.
//!
//! If you implement a suitable back end, by editing a stub or from scratch, move it to src/handlers/, and update src/stubs.rs and
//! src/handlers.rs to reflect the new location. If it is a public MIB that you would like to contribute, make a PR, and I would be delighted
//! to start shipping some more handlers.
//!
//! Two toy implementations of the OidKeeper trait are provided by way of example, both purely memory based. One is for scalars, and the other
//! is a limited table mode. Set can change cell values in existing rows. New rows can be created by the CreateAndWait mechanism if there is a
//! RowStatus column in the table, and destroyed by Destroy. If you change the value of index cells, the results may be puzzling. If the MIB is
//! correctly structured, the permissions checks should stop you making that mistake. The generated stub implementations just wrap the toy
//! struct types, and need to be replaced by real actions.
//!
//! The handlers directory contains a couple of examples of stubs that have been edited to give at least partial implementations
//! of a couple of the core MIBs.
//!
//! ## Trying it out
//!
//! Edit the configuration file .snmp-agent.conf, and insert your Enterprise number and other details.
//!
//! Create a password file called users.txt, using ```python3 tools/usekey.py```. For example,
//!
//! ```shell
//! touch users.txt
//! python3 tools/usekey.py admin myv3user password password1 >> users.txt
//! ```
//! You can run the python tool again to add extra lines to the file for other users.
//!
//! Optionally, edit groups.toml.
//!
//! Set a suitable log level with, for example, ```export RUST_LOG=info```.
//!
//! Run the agent with ```cargo run```.
//!
//! Install netsnmp for testing purposes, and run in another terminal:
//!
//! ```shell
//! snmpwalk -v 3 -l authPriv -a SHA -A password  -x AES -X password1 -u myv3user   127.0.0.1:2161 1.3.6.1 1.3.6.1.6.3
//! ```

pub mod config;
mod engine_id;
pub mod handlers;
pub mod keeper;
mod notifier;
pub mod oidmap;
pub mod perms;
mod privacy;
mod scalar;
pub mod snmp_agent;
pub mod stubs;
mod table;
pub mod usm;
mod utils;