blob: 6779680ff36f968b002c5f9845575452eb53082e [file] [log] [blame]
/*
* 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);
}
}
}