[KARAF-6706] Add SNMP collector
diff --git a/assembly/src/main/feature/feature.xml b/assembly/src/main/feature/feature.xml
index 61d72d9..29fc430 100644
--- a/assembly/src/main/feature/feature.xml
+++ b/assembly/src/main/feature/feature.xml
@@ -241,6 +241,11 @@
<bundle>mvn:org.apache.karaf.decanter.collector/org.apache.karaf.decanter.collector.jetty/${project.version}</bundle>
</feature>
+ <feature name="decanter-collector-snmp" version="${project.version}" description="Karaf Decanter SNMP Collector">
+ <feature>decanter-common</feature>
+ <bundle>mvn:org.apache.karaf.decanter.collector/org.apache.karaf.decanter.collector.snmp/${project.version}</bundle>
+ </feature>
+
<feature name="decanter-appender-log" version="${project.version}" description="Karaf Decanter Log Appender">
<feature>decanter-common</feature>
<configfile finalname="/etc/org.apache.karaf.decanter.appender.log.cfg">mvn:org.apache.karaf.decanter.appender/org.apache.karaf.decanter.appender.log/${project.version}/cfg</configfile>
diff --git a/collector/pom.xml b/collector/pom.xml
index dbecfb1..120b8dc 100644
--- a/collector/pom.xml
+++ b/collector/pom.xml
@@ -54,6 +54,7 @@
<module>rest-servlet</module>
<module>soap</module>
<module>system</module>
+ <module>snmp</module>
<module>socket</module>
<module>prometheus</module>
<module>jdbc</module>
diff --git a/collector/snmp/pom.xml b/collector/snmp/pom.xml
new file mode 100644
index 0000000..8db103c
--- /dev/null
+++ b/collector/snmp/pom.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.karaf.decanter</groupId>
+ <artifactId>collector</artifactId>
+ <version>2.6.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <groupId>org.apache.karaf.decanter.collector</groupId>
+ <artifactId>org.apache.karaf.decanter.collector.snmp</artifactId>
+ <packaging>bundle</packaging>
+ <name>Apache Karaf :: Decanter :: Collector :: SNMP</name>
+
+ <dependencies>
+ <!-- Still using 2.8.6 to work with JDK 8 -->
+ <dependency>
+ <groupId>org.snmp4j</groupId>
+ <artifactId>snmp4j</artifactId>
+ <version>2.8.6</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.decanter.collector</groupId>
+ <artifactId>org.apache.karaf.decanter.collector.utils</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <inherited>true</inherited>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+ <Export-Package>
+ !*
+ </Export-Package>
+ <Import-Package>
+ !org.apache.karaf.decanter.collector.snmp,
+ !org.snmp4j*,
+ *
+ </Import-Package>
+ <Private-Package>
+ org.apache.karaf.decanter.collector.snmp,
+ org.apache.karaf.decanter.collector.utils,
+ org.snmp4j*
+ </Private-Package>
+ <_dsannotations>*</_dsannotations>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
\ No newline at end of file
diff --git a/collector/snmp/src/main/java/org/apache/karaf/decanter/collector/snmp/SnmpPoller.java b/collector/snmp/src/main/java/org/apache/karaf/decanter/collector/snmp/SnmpPoller.java
new file mode 100644
index 0000000..6779680
--- /dev/null
+++ b/collector/snmp/src/main/java/org/apache/karaf/decanter/collector/snmp/SnmpPoller.java
@@ -0,0 +1,283 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.decanter.collector.snmp;
+
+import org.apache.karaf.decanter.collector.utils.PropertiesPreparator;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.annotations.*;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.snmp4j.*;
+import org.snmp4j.event.ResponseEvent;
+import org.snmp4j.event.ResponseListener;
+import org.snmp4j.mp.MPv3;
+import org.snmp4j.mp.SnmpConstants;
+import org.snmp4j.security.*;
+import org.snmp4j.smi.*;
+import org.snmp4j.transport.DefaultTcpTransportMapping;
+import org.snmp4j.transport.DefaultUdpTransportMapping;
+import org.snmp4j.util.DefaultPDUFactory;
+import org.snmp4j.util.TreeEvent;
+import org.snmp4j.util.TreeUtils;
+
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Component(
+ name = "org.apache.karaf.decanter.collector.snmp.poll",
+ immediate = true,
+ configurationPolicy = ConfigurationPolicy.REQUIRE,
+ property = { "decanter.collector.name=snmp",
+ "scheduler.period:Long=60",
+ "scheduler.concurrent:Boolean=false",
+ "scheduler.name=decanter-collector-snmp"
+ }
+)
+public class SnmpPoller implements ResponseListener, Runnable {
+
+ private final static Logger LOGGER = LoggerFactory.getLogger(SnmpPoller.class);
+
+ @Reference
+ private EventAdmin dispatcher;
+
+ private Dictionary<String, Object> configuration;
+ private boolean treeList;
+ private String oids;
+
+ private Address address;
+ private TransportMapping<? extends Address> transport;
+ private Snmp snmp;
+
+ private Target target;
+ private PDU pdu;
+
+ @Activate
+ public void activate(ComponentContext componentContext) throws Exception {
+ activate(componentContext.getProperties());
+ }
+
+ public void activate(Dictionary<String, Object> configuration) throws Exception {
+ this.configuration = configuration;
+
+ String addressConfig = (configuration.get("address") != null) ? (String) configuration.get("address") : "127.0.0.1/161";
+ this.address = GenericAddress.parse(addressConfig);
+
+ String protocol = (configuration.get("protocol") != null) ? (String) configuration.get("protocol") : "tcp";
+ if (protocol.equalsIgnoreCase("tcp")) {
+ this.transport = new DefaultTcpTransportMapping();
+ } else if (protocol.equalsIgnoreCase("udp")) {
+ this.transport = new DefaultUdpTransportMapping();
+ } else {
+ throw new IllegalStateException("Unknown SNMP protocol: " + protocol + " (udp and tcp are supported)");
+ }
+ int retries = (configuration.get("retries") != null) ? Integer.parseInt((String) configuration.get("retries")) : 2;
+ long timeout = (configuration.get("timeout") != null) ? Long.parseLong((String) configuration.get("timeout")) : 1500;
+ treeList = (configuration.get("treelist") != null) ? Boolean.parseBoolean((String) configuration.get("treelist")) : false;
+ oids = (configuration.get("oids") != null) ? (String) configuration.get("oids") : "";
+
+ this.snmp = new Snmp(transport);
+
+ int snmpVersion = (configuration.get("snmp.version") != null) ? Integer.parseInt((String) configuration.get("snmp.version")) : SnmpConstants.version3;
+ if (snmpVersion == SnmpConstants.version3) {
+ UserTarget userTarget = new UserTarget();
+
+ int securityLevel = (configuration.get("security.level") != null) ? Integer.parseInt((String) configuration.get("security.level")) : SecurityLevel.AUTH_PRIV;
+ userTarget.setSecurityLevel(securityLevel);
+ String securityName = (configuration.get("security.name") != null) ? (String) configuration.get("security.name") : "";
+ userTarget.setSecurityName(convertToOctetString(securityName));
+ userTarget.setAddress(address);
+ userTarget.setRetries(2);
+ userTarget.setTimeout(timeout);
+ userTarget.setVersion(snmpVersion);
+
+ this.target = userTarget;
+
+ USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
+ SecurityModels.getInstance().addSecurityModel(usm);
+
+ String authenticationProtocolConfig = (configuration.get("authentication.protocol") != null) ? (String) configuration.get("authentication.protocol") : "MD5";
+ OID authenticationProtocol = convertAuthenticationProtocol(authenticationProtocolConfig);
+
+ String authenticationPassphraseConfig = (configuration.get("authentication.passphrase") != null) ? (String) configuration.get("authentication.passphrase") : "";
+ OctetString authenticationPassphrase = convertToOctetString(authenticationPassphraseConfig);
+
+ String privacyProtocolConfig = (configuration.get("privacy.protocol") != null) ? (String) configuration.get("privacy.protocol") : "DES";
+ OID privacyProtocol = convertPrivacyProtocol(privacyProtocolConfig);
+
+ String privacyPassphraseConfig = (configuration.get("privacy.passphrase") != null) ? (String) configuration.get("privacy.passphrase") : "";
+ OctetString privacyPassphrase = convertToOctetString(privacyPassphraseConfig);
+
+ UsmUser user = new UsmUser(convertToOctetString(securityName), authenticationProtocol,
+ authenticationPassphrase, privacyProtocol, privacyPassphrase);
+ usm.addUser(convertToOctetString(securityName), user);
+
+ ScopedPDU scopedPDU = new ScopedPDU();
+
+ String snmpContextEngineId = (configuration.get("snmp.context.engine.id") != null) ? (String) configuration.get("snmp.context.engine.id") : null;
+ if (snmpContextEngineId != null) {
+ scopedPDU.setContextEngineID(new OctetString(snmpContextEngineId));
+ }
+
+ String snmpContextName = (configuration.get("snmp.context.name") != null) ? (String) configuration.get("snmp.context.name") : null;
+ if (snmpContextName != null) {
+ scopedPDU.setContextName(new OctetString(snmpContextName));
+ }
+
+ this.pdu = scopedPDU;
+ } else {
+ CommunityTarget communityTarget = new CommunityTarget();
+ String snmpCommunity = (configuration.get("snmp.community") != null) ? (String) configuration.get("snmp.community") : "public";
+ communityTarget.setCommunity(convertToOctetString(snmpCommunity));
+ communityTarget.setAddress(address);
+ communityTarget.setRetries(retries);
+ communityTarget.setTimeout(timeout);
+ communityTarget.setVersion(snmpVersion);
+ this.target = communityTarget;
+ this.pdu = new PDU();
+ }
+ this.transport.listen();
+ }
+
+ @Deactivate
+ public void deactivate() throws Exception {
+ if (this.transport != null && this.transport.isListening()) {
+ this.transport.close();
+ }
+ }
+
+ @Override
+ public void run() {
+ this.pdu.clear();
+
+ this.pdu.setType(PDU.GETNEXT);
+
+ if (!treeList) {
+ for (String oid : oids.split(",")) {
+ this.pdu.add(new VariableBinding(new OID(oid)));
+ }
+ } else {
+ TreeUtils treeUtils = new TreeUtils(snmp, new DefaultPDUFactory());
+ for (String oid : oids.split(",")) {
+ List events = treeUtils.getSubtree(target, new OID(oid));
+ for (Object event : events) {
+ TreeEvent treeEvent = (TreeEvent) event;
+ if (treeEvent == null) {
+ LOGGER.warn("SNMP event is null");
+ continue;
+ }
+ if (treeEvent.isError()) {
+ LOGGER.error("Error in SNMP event: {}", treeEvent.getErrorMessage());
+ continue;
+ }
+ VariableBinding[] variableBindings = treeEvent.getVariableBindings();
+ if (variableBindings == null || variableBindings.length == 0) {
+ continue;
+ }
+ for (VariableBinding variableBinding : variableBindings) {
+ if (variableBinding == null) {
+ continue;
+ }
+ this.pdu.add(variableBinding);
+ }
+ }
+ }
+ }
+ try {
+ snmp.send(pdu, target, null, this);
+ } catch (Exception e) {
+ LOGGER.warn("Can't send SNMP request", e);
+ }
+ }
+
+ @Override
+ public void onResponse(ResponseEvent event) {
+ ((Snmp) event.getSource()).cancel(event.getRequest(), this);
+
+ if (event.getRequest() == null || event.getResponse() == null) {
+ return;
+ }
+
+ PDU pdu = event.getResponse();
+ Map<String, Object> data = new HashMap<>();
+ data.put("type", "snmp.poll");
+ data.put("peerAddress", event.getPeerAddress());
+ try {
+ PropertiesPreparator.prepare(data, configuration);
+ } catch (Exception e) {
+ LOGGER.warn("Can't prepare event data", e);
+ }
+ // PDU v1 specific variables
+ if (pdu.getType() == PDU.V1TRAP) {
+ PDUv1 v1pdu = (PDUv1) pdu;
+ data.put("enterprise", v1pdu.getEnterprise().toString());
+ data.put("agentAddress", v1pdu.getAgentAddress().toString());
+ data.put("genericTrap", v1pdu.getGenericTrap());
+ data.put("specificTrap", v1pdu.getSpecificTrap());
+ data.put("timestamp", v1pdu.getTimestamp());
+ }
+ // all variables
+ for (VariableBinding variableBinding : pdu.getVariableBindings()) {
+ data.put(variableBinding.getOid().toString(), variableBinding.getVariable().toString());
+ }
+ // send event
+ dispatcher.postEvent(new Event("decanter/collector/snmp", data));
+ }
+
+ private OctetString convertToOctetString(String value) {
+ if (value == null) {
+ return null;
+ }
+ return new OctetString(value);
+ }
+
+ private OID convertAuthenticationProtocol(String authenticationProtocol) {
+ if (authenticationProtocol == null) {
+ return null;
+ }
+ if (authenticationProtocol.equals("MD5")) {
+ return AuthMD5.ID;
+ } else if (authenticationProtocol.equals("SHA1")) {
+ return AuthSHA.ID;
+ } else {
+ throw new IllegalArgumentException("Unknown authentication protocol: " + authenticationProtocol);
+ }
+ }
+
+ private OID convertPrivacyProtocol(String privacyProtocol) {
+ if (privacyProtocol == null) {
+ return null;
+ }
+ if (privacyProtocol.equals("DES")) {
+ return PrivDES.ID;
+ } else if (privacyProtocol.equals("TRIDES")) {
+ return Priv3DES.ID;
+ } else if (privacyProtocol.equals("AES128")) {
+ return PrivAES128.ID;
+ } else if (privacyProtocol.equals("AES192")) {
+ return PrivAES192.ID;
+ } else if (privacyProtocol.equals("AES256")) {
+ return PrivAES256.ID;
+ } else {
+ throw new IllegalArgumentException("Unknown privacy protocol: " + privacyProtocol);
+ }
+ }
+
+}
diff --git a/collector/snmp/src/main/java/org/apache/karaf/decanter/collector/snmp/SnmpTrap.java b/collector/snmp/src/main/java/org/apache/karaf/decanter/collector/snmp/SnmpTrap.java
new file mode 100644
index 0000000..a29cecf
--- /dev/null
+++ b/collector/snmp/src/main/java/org/apache/karaf/decanter/collector/snmp/SnmpTrap.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.decanter.collector.snmp;
+
+import org.apache.karaf.decanter.collector.utils.PropertiesPreparator;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.annotations.*;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.snmp4j.*;
+import org.snmp4j.mp.StateReference;
+import org.snmp4j.mp.StatusInformation;
+import org.snmp4j.smi.*;
+import org.snmp4j.transport.DefaultTcpTransportMapping;
+import org.snmp4j.transport.DefaultUdpTransportMapping;
+
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Map;
+
+@Component(
+ name = "org.apache.karaf.decanter.collector.snmp.trap",
+ immediate = true,
+ configurationPolicy = ConfigurationPolicy.REQUIRE
+)
+public class SnmpTrap implements CommandResponder {
+
+ private final static Logger LOGGER = LoggerFactory.getLogger(SnmpTrap.class);
+
+ @Reference
+ private EventAdmin dispatcher;
+
+ private Dictionary<String, Object> configuration;
+
+ private Address address;
+ private Snmp snmp;
+ private TransportMapping<? extends Address> transport;
+
+ @Activate
+ public void activate(ComponentContext componentContext) throws Exception {
+ activate(componentContext.getProperties());
+ }
+
+ public void activate(Dictionary<String, Object> configuration) throws Exception {
+ this.configuration = configuration;
+ String addressConfig = (configuration.get("address") != null) ? (String) configuration.get("address") : "127.0.0.1/161";
+ this.address = GenericAddress.parse(addressConfig);
+
+ String protocol = (configuration.get("protocol") != null) ? (String) configuration.get("protocol") : "tcp";
+ if (protocol.equalsIgnoreCase("tcp")) {
+ transport = new DefaultTcpTransportMapping((TcpAddress) address);
+ } else if (protocol.equalsIgnoreCase("udp")) {
+ transport = new DefaultUdpTransportMapping((UdpAddress) address);
+ } else {
+ throw new IllegalArgumentException("Unknown SNMP protocol: " + protocol + " (should be tcp or udp)");
+ }
+ this.snmp = new Snmp(transport);
+ this.snmp.addCommandResponder(this);
+ this.snmp.listen();
+ }
+
+ @Deactivate
+ public void deactivate() throws Exception {
+ transport.close();
+ }
+
+ @Override
+ public void processPdu(CommandResponderEvent event) {
+ PDU pdu = event.getPDU();
+ if (pdu != null) {
+ try {
+ if ((pdu.getType() != PDU.TRAP) && (pdu.getType() != PDU.V1TRAP) && (pdu.getType() != PDU.REPORT) && (pdu.getType() != PDU.RESPONSE)) {
+ // respond the inform message
+ pdu.setErrorIndex(0);
+ pdu.setErrorStatus(0);
+ pdu.setType(PDU.RESPONSE);
+ StatusInformation statusInformation = new StatusInformation();
+ StateReference reference = event.getStateReference();
+ event.getMessageDispatcher().returnResponsePdu(event.getMessageProcessingModel(),
+ event.getSecurityModel(),
+ event.getSecurityName(),
+ event.getSecurityModel(),
+ pdu,
+ event.getMaxSizeResponsePDU(),
+ reference,
+ statusInformation);
+ }
+ Map<String, Object> data = new HashMap<>();
+ data.put("type", "snmp.trap");
+ data.put("securityName", new OctetString(event.getSecurityName()));
+ data.put("peerAddress", event.getPeerAddress());
+ PropertiesPreparator.prepare(data, configuration);
+ // PDU v1 specific variables
+ if (pdu.getType() == PDU.V1TRAP) {
+ PDUv1 v1pdu = (PDUv1) pdu;
+ data.put("enterprise", v1pdu.getEnterprise().toString());
+ data.put("agentAddress", v1pdu.getAgentAddress().toString());
+ data.put("genericTrap", v1pdu.getGenericTrap());
+ data.put("specificTrap", v1pdu.getSpecificTrap());
+ data.put("timestamp", v1pdu.getTimestamp());
+ }
+ // all variables
+ for (VariableBinding variableBinding : pdu.getVariableBindings()) {
+ data.put(variableBinding.getOid().toString(), variableBinding.getVariable().toString());
+ }
+ // send event
+ dispatcher.postEvent(new Event("decanter/collector/snmp", data));
+ } catch (Exception e) {
+ LOGGER.warn("Can't send SNMP event", e);
+ }
+ }
+ }
+
+}
diff --git a/manual/src/main/asciidoc/user-guide/collectors.adoc b/manual/src/main/asciidoc/user-guide/collectors.adoc
index ddc92c3..02a60f0 100644
--- a/manual/src/main/asciidoc/user-guide/collectors.adoc
+++ b/manual/src/main/asciidoc/user-guide/collectors.adoc
@@ -1086,6 +1086,70 @@
The collector automatically registers in the Pax Web Jetty container and then all HTTP requests/responses data will be sent to the appenders.
+==== SNMP
+
+Decanter SNMP Collector allows you to trap or poll metrics from SNMP.
+
+The `decanter-collector-snmp` feature installs the SNMP collector:
+
+----
+karaf@root()> feature:install decanter-collector-snmp
+----
+
+Actually, this collector provides two kind of collectors: poller or trap.
+
+===== Trap
+
+If you want to use SNMP trap, you have to create `etc/org.apache.karaf.decanter.collector.snmp.trap.cfg` configuration file containing:
+
+----
+address=127.0.0.1:161
+protocol=tcp
+----
+
+* `address` is the listening SNMP trap address
+* `protocol` is the transport protocol (TCP or UDP).
+
+===== Poll
+
+If you want to use SNMP poller (periodically getting SNMP metrics), you have to create `etc/org.apache.karaf.decanter.collector.snmp.poll.cfg` configuration file containing:
+
+----
+address=127.0.0.1:161
+protocol=tcp
+retries=2
+timeout=1500
+treelist=false
+oids=first,second
+snmp.version=3
+security.level=3
+security.name=security
+authentication.protocol=MD5
+authentication.passphrase=pass
+privacy.protocol=DES
+privacy.passphrase=pass
+#snmp.context.engine.id=foo
+#snmp.context.name=foo
+snmp.community=public
+----
+
+* `address` is the SNMP service address
+* `protocol` is the transport protocol (tcp or udp)
+* `retries` is the number of attempts
+* `timeout` is the SNMP request timeout (in ms)
+* `treelist` is true to request SNMP tree, false else
+* `oids` is the list of SNMP OIDs to request
+* `snmp.version` is the SNMP version to use (3 by default)
+* `security.level` is the level of security expected by the SNMP version (3 == AUTH_PRIV by default)
+* `security.name` is the security name alias
+* `authentication.protocol` is the password protocol (MD5 or SHA1)
+* `authentication.passphrase` is the password/passphrase to use
+* `privacy.protocol` is DES, TRIDES, AES128, AES192, AES256
+* `private.passphrase` is the password/passphrase to use
+* `snmp.context.engine.id` is optional
+* `snmp.context.name` is optional
+* `snmp.community` is the community to use, `public` by default
+
==== Customizing properties in collectors
You can add, rename or remove properties collected by the collectors before sending it to the dispatcher.
@@ -1111,4 +1175,4 @@
----
fields.rename.helo=hello
- ----
+ ----
\ No newline at end of file